All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code
@ 2018-02-11  9:35 Markus Armbruster
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
                   ` (31 more replies)
  0 siblings, 32 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Our qapi-schema.json is composed of modules connected by include
directives, but the generated code is monolithic all the same: one
qapi-types.h with all the types, one qapi-visit.h with all the
visitors, and so forth.  These monolithic headers get included all
over the place.  In my "build everything" tree, adding a QAPI type
recompiles about 4800 out of 5100 objects.

We wouldn't write such monolithic headers by hand.  It stands to
reason that we shouldn't generate them, either.

This series' basic idea is to split up generated headers to mirror the
schema's modular structure: one header per module.  That way, you can
include just what you need.

The compile-time improvements can be massive.  Before this series, any
QAPI schema change recompiles some 4800 out of 5100 objects in my
"build everything" tree.  Afterwards, adding a type to
qapi/migration.json recompiles a bit over 100, and a documentation
change no longer recompiles anything.

Related: Marc-André's 'unit' pragma proposal.  That's a different way
to split off parts of the generated code, motivated by the desire to
use poisoned identifiers such as TARGET_I386.  I noted in my review of
v3 that I "can either accept it, or come up with a better solution."
This is my attempt at a better solution.  It's a bit more ambitious,
and thus more useful (I hope).  The pragma has one theoretical
advantage, though: you can modularize the generated output in
different ways than the input.  The patches using don't do that,
however.

v2:
* Rebased, annoying conflicts due to the Python 2 rigmarole
* PATCH 01: New
* PATCH 02-03,08,10-11,17,19-24: Commit messages improved
  [Eric, Marc-André]
* PATCH 04: Split off the next patch [Eric]
* PATCH 05,07-08,10,19: QAPIGen methods renamed [Marc-André]
* PATCH 08,20,22: fix missing .gitignore updates
* PATCH 08:
  - generated doc renamed to qapi-doc.texi
  - qapi-code-gen.txt updated
  - useless options -c, -h dropped
* PATCH 09: New, replacing old PATCH 07
* PATCH 16: Latent bug in QAPISchema.check() fixed
* PATCH 18: New
* PATCH 19-20,22-24:
  - Common code factored out into QAPISchemaMonolithicCVisitor
    and QAPISchemaModularCVisitor
  - All code-generating visitors covered
  - Consistent parameter order prefix, opt_builtins
  - R-bys dropped
* PATCH 25-29: New

Markus Armbruster (29):
  Include qapi/qmp/qerror.h exactly where needed
  qapi: Streamline boilerplate comment generation
  qapi: Generate up-to-date copyright notice
  qapi: Rename variable holding the QAPISchemaGenFOOVisitor
  qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
  qapi: Reduce use of global variables in generators some
  qapi: Turn generators into modules
  qapi-gen: New common driver for code and doc generators
  qapi-gen: Convert from getopt to argparse
  qapi: Touch generated files only when they change
  qapi: Improve include file name reporting in error messages
  qapi/common: Eliminate QAPISchema.exprs
  qapi: Lift error reporting from QAPISchema.__init__() to callers
  qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
  qapi: Record 'include' directives in parse tree
  qapi: Generate in source order
  qapi: Record 'include' directives in intermediate representation
  qapi: Rename generated qmp-marshal.c to qmp-commands.c
  qapi: Make code-generating visitors use QAPIGen more
  qapi/types qapi/visit: Generate built-in stuff into separate files
  qapi/common: Fix guardname() for funny filenames
  qapi: Generate separate .h, .c for each module
  Include less of the generated modular QAPI headers
  qapi: Empty out qapi-schema.json
  docs/devel/writing-qmp-commands: Update for modular QAPI
  docs: Correct outdated information on QAPI
  qapi: Move qapi-schema.json to qapi/, rename generated files
  Fix up dangling references to qmp-commands.* in comment and doc
  qapi: Don't create useless directory qapi-generated

 .gitignore                                         |  80 ++++-
 Makefile                                           | 233 ++++++++++----
 Makefile.objs                                      |  80 ++++-
 arch_init.c                                        |   2 +-
 backends/cryptodev.c                               |   1 -
 backends/hostmem.c                                 |   3 +-
 balloon.c                                          |   2 +-
 block.c                                            |   2 -
 block/block-backend.c                              |   2 +-
 block/crypto.c                                     |   2 +-
 block/iscsi.c                                      |   2 +-
 block/nbd.c                                        |   2 +-
 block/nfs.c                                        |   2 +-
 block/qapi.c                                       |   4 +-
 block/qcow2.c                                      |   4 +-
 block/quorum.c                                     |   2 +-
 block/sheepdog.c                                   |   2 +-
 block/ssh.c                                        |   2 +-
 block/throttle-groups.c                            |   2 +-
 block/write-threshold.c                            |   4 +-
 blockdev-nbd.c                                     |   2 +-
 blockdev.c                                         |   5 +-
 blockjob.c                                         |   2 +-
 chardev/char-fe.c                                  |   2 +-
 chardev/char-ringbuf.c                             |   2 +-
 chardev/char-socket.c                              |   1 +
 chardev/char.c                                     |   4 +-
 configure                                          |   1 -
 cpus.c                                             |   4 +-
 crypto/cipherpriv.h                                |   2 +-
 docs/devel/qapi-code-gen.txt                       | 119 ++++---
 docs/devel/writing-qmp-commands.txt                |  39 +--
 docs/interop/qmp-intro.txt                         |   3 +-
 docs/xen-save-devices-state.txt                    |   3 +-
 dump.c                                             |   4 +-
 hmp.c                                              |  12 +-
 hw/acpi/core.c                                     |   4 +-
 hw/acpi/cpu.c                                      |   2 +-
 hw/acpi/memory_hotplug.c                           |   2 +-
 hw/acpi/vmgenid.c                                  |   2 +-
 hw/block/block.c                                   |   1 +
 hw/block/hd-geometry.c                             |   1 +
 hw/char/virtio-console.c                           |   2 +-
 hw/core/machine.c                                  |   2 +-
 hw/core/qdev.c                                     |   2 +-
 hw/i386/pc.c                                       |   2 +-
 hw/i386/xen/xen-hvm.c                              |   2 +-
 hw/ipmi/ipmi.c                                     |   2 +-
 hw/mem/nvdimm.c                                    |   1 -
 hw/net/rocker/qmp-norocker.c                       |   2 +-
 hw/net/rocker/rocker.c                             |   2 +-
 hw/net/rocker/rocker_fp.c                          |   2 +-
 hw/net/rocker/rocker_of_dpa.c                      |   2 +-
 hw/net/virtio-net.c                                |   2 +-
 hw/pci/pci-stub.c                                  |   2 +-
 hw/pci/pci.c                                       |   2 +-
 hw/ppc/spapr_rtas.c                                |   1 -
 hw/ppc/spapr_rtc.c                                 |   2 +-
 hw/s390x/s390-skeys.c                              |   2 +-
 hw/timer/mc146818rtc.c                             |   4 +-
 hw/tpm/tpm_emulator.c                              |   1 +
 hw/tpm/tpm_passthrough.c                           |   1 +
 hw/virtio/virtio-balloon.c                         |   2 +-
 hw/watchdog/watchdog.c                             |   4 +-
 include/block/block.h                              |   2 +-
 include/block/dirty-bitmap.h                       |   2 +-
 include/block/nbd.h                                |   2 +-
 include/chardev/char.h                             |   1 +
 include/crypto/cipher.h                            |   2 +-
 include/crypto/hash.h                              |   2 +-
 include/crypto/hmac.h                              |   2 +-
 include/crypto/secret.h                            |   1 +
 include/crypto/tlscreds.h                          |   1 +
 include/hw/block/block.h                           |   2 +-
 include/hw/block/fdc.h                             |   2 +-
 include/hw/ppc/spapr_drc.h                         |   1 +
 include/hw/qdev-properties.h                       |   2 +
 include/io/dns-resolver.h                          |   1 +
 include/migration/colo.h                           |   2 +-
 include/migration/failover.h                       |   2 +-
 include/migration/global_state.h                   |   1 +
 include/monitor/monitor.h                          |   1 +
 include/net/filter.h                               |   1 +
 include/net/net.h                                  |   2 +-
 include/qapi/clone-visitor.h                       |   1 -
 include/qapi/error.h                               |   2 +-
 include/qapi/qmp/qobject.h                         |   2 +-
 include/qapi/visitor.h                             |   2 +-
 include/qemu/sockets.h                             |   2 +-
 include/qemu/throttle.h                            |   2 +-
 include/qom/cpu.h                                  |   1 +
 include/qom/object.h                               |   2 +-
 include/sysemu/arch_init.h                         |   2 +-
 include/sysemu/balloon.h                           |   2 +-
 include/sysemu/dump.h                              |   2 +
 include/sysemu/hostmem.h                           |   1 +
 include/sysemu/replay.h                            |   2 +
 include/sysemu/sysemu.h                            |   1 +
 include/sysemu/tpm.h                               |   1 +
 include/sysemu/watchdog.h                          |   2 +-
 include/ui/input.h                                 |   2 +-
 io/channel-socket.c                                |   1 +
 io/dns-resolver.c                                  |   1 +
 iothread.c                                         |   2 +-
 migration/colo-failover.c                          |   2 +-
 migration/colo.c                                   |   2 +-
 migration/migration.c                              |   4 +-
 migration/migration.h                              |   1 +
 migration/ram.c                                    |   2 +-
 migration/ram.h                                    |   2 +-
 migration/savevm.c                                 |   3 +-
 monitor.c                                          |   8 +-
 net/colo-compare.c                                 |   1 -
 net/filter-buffer.c                                |   2 +-
 net/filter-mirror.c                                |   1 -
 net/filter-rewriter.c                              |   1 -
 net/net.c                                          |   4 +-
 net/tap_int.h                                      |   2 +-
 net/vhost-user.c                                   |   2 +-
 numa.c                                             |   4 +-
 qapi-schema.json => qapi/misc.json                 | 105 +-----
 qapi/qapi-schema.json                              |  95 ++++++
 qapi/run-state.json                                |  10 +
 qdev-monitor.c                                     |   2 +-
 qemu-img.c                                         |   2 +-
 qga/Makefile.objs                                  |   2 +-
 qga/commands-posix.c                               |   2 +-
 qga/commands-win32.c                               |   2 +-
 qga/commands.c                                     |   2 +-
 qga/main.c                                         |   2 +-
 qmp.c                                              |  18 +-
 qom/object.c                                       |   2 +-
 qom/object_interfaces.c                            |   2 +-
 replay/replay-input.c                              |   1 +
 replication.h                                      |   1 +
 scripts/qapi-gen.py                                |  57 ++++
 scripts/qapi/__init__.py                           |   0
 scripts/{qapi-commands.py => qapi/commands.py}     | 155 ++++-----
 scripts/{qapi.py => qapi/common.py}                | 355 +++++++++++++--------
 scripts/{qapi2texi.py => qapi/doc.py}              |  92 +++---
 scripts/{qapi-event.py => qapi/events.py}          | 128 +++-----
 scripts/{qapi-introspect.py => qapi/introspect.py} | 123 +++----
 scripts/{qapi-types.py => qapi/types.py}           | 185 ++++-------
 scripts/{qapi-visit.py => qapi/visit.py}           | 189 ++++-------
 stubs/tpm.c                                        |   3 +-
 stubs/uuid.c                                       |   2 +-
 stubs/vmgenid.c                                    |   2 +-
 stubs/xen-hvm.c                                    |   2 +-
 target/arm/monitor.c                               |   3 +-
 target/i386/cpu.c                                  |   4 +-
 target/s390x/kvm.c                                 |   1 -
 tests/.gitignore                                   |   9 +-
 tests/Makefile.include                             |  70 ++--
 tests/qapi-schema/comments.out                     |   3 +-
 tests/qapi-schema/doc-bad-section.out              |   5 +-
 tests/qapi-schema/doc-good.out                     |  33 +-
 tests/qapi-schema/doc-good.texi                    |   3 +-
 tests/qapi-schema/empty.out                        |   2 +-
 tests/qapi-schema/event-case.out                   |   3 +-
 tests/qapi-schema/ident-with-escape.out            |   7 +-
 tests/qapi-schema/include-no-file.err              |   2 +-
 tests/qapi-schema/include-relpath.out              |   7 +-
 tests/qapi-schema/include-repetition.out           |  12 +-
 tests/qapi-schema/include-simple.out               |   5 +-
 tests/qapi-schema/indented-expr.out                |   3 +-
 tests/qapi-schema/qapi-schema-test.out             | 321 +++++++++----------
 tests/qapi-schema/test-qapi.py                     |  19 +-
 tests/qmp-test.c                                   |   3 +-
 tests/test-char.c                                  |   2 +-
 tests/{test-qmp-commands.c => test-qmp-cmds.c}     |   2 +-
 tests/test-qmp-event.c                             |   3 +-
 tests/test-qobject-input-visitor.c                 |   8 +-
 tests/test-visitor-serialization.c                 |   1 -
 tpm.c                                              |   3 +-
 trace/qmp.c                                        |   2 +-
 ui/cocoa.m                                         |   2 +-
 ui/console.c                                       |   2 +-
 ui/gtk.c                                           |   2 +-
 ui/input-legacy.c                                  |   2 +-
 ui/input.c                                         |   2 +-
 ui/spice-core.c                                    |   4 +-
 ui/vnc.c                                           |   4 +-
 ui/vnc.h                                           |   1 +
 util/qemu-config.c                                 |   2 +-
 util/qemu-sockets.c                                |   2 +-
 vl.c                                               |   8 +-
 186 files changed, 1556 insertions(+), 1352 deletions(-)
 rename qapi-schema.json => qapi/misc.json (95%)
 create mode 100644 qapi/qapi-schema.json
 create mode 100755 scripts/qapi-gen.py
 create mode 100644 scripts/qapi/__init__.py
 rename scripts/{qapi-commands.py => qapi/commands.py} (67%)
 rename scripts/{qapi.py => qapi/common.py} (90%)
 rename scripts/{qapi2texi.py => qapi/doc.py} (78%)
 mode change 100755 => 100644
 rename scripts/{qapi-event.py => qapi/events.py} (61%)
 rename scripts/{qapi-introspect.py => qapi/introspect.py} (71%)
 rename scripts/{qapi-types.py => qapi/types.py} (53%)
 rename scripts/{qapi-visit.py => qapi/visit.py} (64%)
 rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (99%)

-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 16:55   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation Markus Armbruster
                   ` (30 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c                 | 1 -
 block/qcow2.c           | 1 -
 chardev/char-fe.c       | 1 +
 chardev/char.c          | 1 +
 qom/object_interfaces.c | 1 +
 scripts/qapi-visit.py   | 2 +-
 6 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/block.c b/block.c
index f94585b230..05a484b4b8 100644
--- a/block.c
+++ b/block.c
@@ -32,7 +32,6 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qstring.h"
 #include "sysemu/block-backend.h"
diff --git a/block/qcow2.c b/block/qcow2.c
index a64a572785..9245deac19 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -30,7 +30,6 @@
 #include "block/qcow2.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi-event.h"
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index c611b3fa3e..e5f870e4d2 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -24,6 +24,7 @@
 #include "qemu/osdep.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi-visit.h"
 #include "sysemu/replay.h"
 
diff --git a/chardev/char.c b/chardev/char.c
index 01d979a1da..c9a4da5516 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -32,6 +32,7 @@
 #include "qmp-commands.h"
 #include "qapi-visit.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
 #include "sysemu/replay.h"
 #include "qemu/help_option.h"
 #include "qemu/option.h"
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 80d09139be..43d9aa0946 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -1,6 +1,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qerror.h"
 #include "qom/object_interfaces.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 7e1cfc13f0..bc2b8b581a 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -371,13 +371,13 @@ fdef.write(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
                  prefix=prefix))
 
 fdecl.write(mcgen('''
 #include "qapi/visitor.h"
-#include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Every generator has separate boilerplate for .h and .c, and their
differences are boring.  All of them repeat the license note.

Reduce the repetition as follows.  Move common text like the license
note to common open_output(), next to the existing common text there.
For each generator, replace the two separate descriptions by a single
one.

While there, emit an "automatically generated" note into generated
documentation, too.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py        | 26 +++-----------------------
 scripts/qapi-event.py           | 26 +++-----------------------
 scripts/qapi-introspect.py      | 21 ++-------------------
 scripts/qapi-types.py           | 26 +++-----------------------
 scripts/qapi-visit.py           | 26 +++-----------------------
 scripts/qapi.py                 | 31 ++++++++++++++++++-------------
 scripts/qapi2texi.py            |  3 ++-
 tests/qapi-schema/doc-good.texi |  3 ++-
 8 files changed, 36 insertions(+), 126 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index f89d748ba4..8e8da7c796 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -255,38 +255,18 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
 
 (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
 
-c_comment = '''
-/*
- * schema-defined QMP->QAPI command dispatch
+blurb = '''
+ * Schema-defined QAPI/QMP commands
  *
  * Copyright IBM, Corp. 2011
  *
  * Authors:
  *  Anthony Liguori   <aliguori@us.ibm.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.
- *
- */
-'''
-h_comment = '''
-/*
- * schema-defined QAPI function prototypes
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.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.
- *
- */
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qmp-marshal.c', 'qmp-commands.h',
-                            c_comment, h_comment)
+                            blurb)
 
 fdef.write(mcgen('''
 
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index c710968dc2..2b7d720c08 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -171,38 +171,18 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
 
 (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
 
-c_comment = '''
-/*
- * schema-defined QAPI event functions
+blurb = '''
+ * Schema-defined QAPI/QMP events
  *
  * Copyright (c) 2014 Wenchao Xia
  *
  * Authors:
  *  Wenchao Xia   <wenchaoqemu@gmail.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.
- *
- */
-'''
-h_comment = '''
-/*
- * schema-defined QAPI event functions
- *
- * Copyright (c) 2014 Wenchao Xia
- *
- * Authors:
- *  Wenchao Xia  <wenchaoqemu@gmail.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.
- *
- */
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-event.c', 'qapi-event.h',
-                            c_comment, h_comment)
+                            blurb)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 032bcea491..83da2bdb94 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -176,32 +176,15 @@ for o, a in opts:
     if o in ('-u', '--unmask-non-abi-names'):
         opt_unmask = True
 
-c_comment = '''
-/*
+blurb = '''
  * QAPI/QMP schema introspection
  *
  * Copyright (C) 2015 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.
- *
- */
-'''
-h_comment = '''
-/*
- * QAPI/QMP schema introspection
- *
- * Copyright (C) 2015 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.
- *
- */
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qmp-introspect.c', 'qmp-introspect.h',
-                            c_comment, h_comment)
+                            blurb)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 7e3051dbb9..86afc57f92 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -250,39 +250,19 @@ for o, a in opts:
     if o in ('-b', '--builtins'):
         do_builtins = True
 
-c_comment = '''
-/*
- * deallocation functions for schema-defined QAPI types
+blurb = '''
+ * Schema-defined QAPI types
  *
  * Copyright IBM, Corp. 2011
  *
  * Authors:
  *  Anthony Liguori   <aliguori@us.ibm.com>
  *  Michael Roth      <mdroth@linux.vnet.ibm.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.
- *
- */
-'''
-h_comment = '''
-/*
- * schema-defined QAPI types
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.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.
- *
- */
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-types.c', 'qapi-types.h',
-                            c_comment, h_comment)
+                            blurb)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index bc2b8b581a..0a367072fb 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -334,38 +334,18 @@ for o, a in opts:
     if o in ('-b', '--builtins'):
         do_builtins = True
 
-c_comment = '''
-/*
- * schema-defined QAPI visitor functions
+blurb = '''
+ * Schema-defined QAPI visitors
  *
  * Copyright IBM, Corp. 2011
  *
  * Authors:
  *  Anthony Liguori   <aliguori@us.ibm.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.
- *
- */
-'''
-h_comment = '''
-/*
- * schema-defined QAPI visitor functions
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.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.
- *
- */
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-visit.c', 'qapi-visit.h',
-                            c_comment, h_comment)
+                            blurb)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 58f995b07f..2e5a1ce6a8 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1985,11 +1985,21 @@ def parse_command_line(extra_options='', extra_long_options=[]):
 #
 
 
-def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
-                c_comment, h_comment):
+def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb):
     guard = guardname(prefix + h_file)
     c_file = output_dir + prefix + c_file
     h_file = output_dir + prefix + h_file
+    comment = mcgen('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+%(blurb)s
+ *
+ * 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.
+ */
+
+''',
+                    blurb=blurb.strip('\n'))
 
     if output_dir:
         try:
@@ -2007,27 +2017,22 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
     fdef = maybe_open(do_c, c_file, 'w')
     fdecl = maybe_open(do_h, h_file, 'w')
 
-    fdef.write(mcgen('''
-/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
-%(comment)s
-''',
-                     comment=c_comment))
-
+    fdef.write(comment)
+    fdecl.write(comment)
     fdecl.write(mcgen('''
-/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
-%(comment)s
 #ifndef %(guard)s
 #define %(guard)s
 
 ''',
-                      comment=h_comment, guard=guard))
+                      guard=guard))
 
     return (fdef, fdecl)
 
 
 def close_output(fdef, fdecl):
-    fdecl.write('''
+    fdecl.write(mcgen('''
+
 #endif
-''')
+'''))
     fdecl.close()
     fdef.close()
diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index bf1c57b2e2..8a604d86a6 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -283,7 +283,8 @@ def main(argv):
         print("%s: need pragma 'doc-required' "
                "to generate documentation" % argv[0], file=sys.stderr)
         sys.exit(1)
-    print(texi_schema(schema))
+    print('@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n')
+    print(texi_schema(schema), end='')
 
 
 if __name__ == '__main__':
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 1778312581..0aed2300a5 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -1,3 +1,5 @@
+@c AUTOMATICALLY GENERATED, DO NOT MODIFY
+
 @section Section
 
 @subsection Subsection
@@ -231,4 +233,3 @@ If you're bored enough to read this, go see a video of boxed cats
 
 @end deftypefn
 
-
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:40   ` Eric Blake
  2018-02-16 22:53   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
                   ` (28 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Each generator carries a copyright notice for the generator itself,
and another one for the files it generates.  Only the former have been
updated along the way, the latter have not, and are all out of date.

Fix by copying the generator's copyright notice to the generated files
instead.  Note that the fix doesn't copy the "Authors:" part; the
generated files' outdated Authors list goes away without replacement.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py   | 34 +++++++++++++++-------------------
 scripts/qapi-event.py      | 32 ++++++++++++++------------------
 scripts/qapi-introspect.py | 25 ++++++++++++-------------
 scripts/qapi-types.py      | 32 ++++++++++++++------------------
 scripts/qapi-visit.py      | 34 +++++++++++++++-------------------
 scripts/qapi.py            |  7 +++++--
 6 files changed, 75 insertions(+), 89 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 8e8da7c796..84a980d882 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -1,16 +1,17 @@
-#
-# QAPI command marshaller generator
-#
-# Copyright IBM, Corp. 2011
-# Copyright (C) 2014-2016 Red Hat, Inc.
-#
-# Authors:
-#  Anthony Liguori <aliguori@us.ibm.com>
-#  Michael Roth    <mdroth@linux.vnet.ibm.com>
-#  Markus Armbruster <armbru@redhat.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.
-# See the COPYING file in the top-level directory.
+"""
+QAPI command marshaller generator
+
+Copyright IBM, Corp. 2011
+Copyright (C) 2014-2018 Red Hat, Inc.
+
+Authors:
+ Anthony Liguori <aliguori@us.ibm.com>
+ Michael Roth <mdroth@linux.vnet.ibm.com>
+ Markus Armbruster <armbru@redhat.com>
+
+This work is licensed under the terms of the GNU GPL, version 2.
+See the COPYING file in the top-level directory.
+"""
 
 from qapi import *
 
@@ -257,16 +258,11 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
 
 blurb = '''
  * Schema-defined QAPI/QMP commands
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qmp-marshal.c', 'qmp-commands.h',
-                            blurb)
+                            blurb, __doc__)
 
 fdef.write(mcgen('''
 
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 2b7d720c08..0a098803e2 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -1,15 +1,16 @@
-#
-# QAPI event generator
-#
-# Copyright (c) 2014 Wenchao Xia
-# Copyright (c) 2015-2016 Red Hat Inc.
-#
-# Authors:
-#  Wenchao Xia <wenchaoqemu@gmail.com>
-#  Markus Armbruster <armbru@redhat.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.
-# See the COPYING file in the top-level directory.
+"""
+QAPI event generator
+
+Copyright (c) 2014 Wenchao Xia
+Copyright (c) 2015-2018 Red Hat Inc.
+
+Authors:
+ Wenchao Xia <wenchaoqemu@gmail.com>
+ Markus Armbruster <armbru@redhat.com>
+
+This work is licensed under the terms of the GNU GPL, version 2.
+See the COPYING file in the top-level directory.
+"""
 
 from qapi import *
 
@@ -173,16 +174,11 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
 
 blurb = '''
  * Schema-defined QAPI/QMP events
- *
- * Copyright (c) 2014 Wenchao Xia
- *
- * Authors:
- *  Wenchao Xia   <wenchaoqemu@gmail.com>
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-event.c', 'qapi-event.h',
-                            blurb)
+                            blurb, __doc__)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 83da2bdb94..bd9253a172 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -1,13 +1,14 @@
-#
-# QAPI introspection generator
-#
-# Copyright (C) 2015-2016 Red Hat, Inc.
-#
-# Authors:
-#  Markus Armbruster <armbru@redhat.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.
-# See the COPYING file in the top-level directory.
+"""
+QAPI introspection generator
+
+Copyright (C) 2015-2018 Red Hat, Inc.
+
+Authors:
+ Markus Armbruster <armbru@redhat.com>
+
+This work is licensed under the terms of the GNU GPL, version 2.
+See the COPYING file in the top-level directory.
+"""
 
 from qapi import *
 
@@ -178,13 +179,11 @@ for o, a in opts:
 
 blurb = '''
  * QAPI/QMP schema introspection
- *
- * Copyright (C) 2015 Red Hat, Inc.
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qmp-introspect.c', 'qmp-introspect.h',
-                            blurb)
+                            blurb, __doc__)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 86afc57f92..1103dbda2d 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -1,15 +1,17 @@
-#
-# QAPI types generator
-#
-# Copyright IBM, Corp. 2011
-# Copyright (c) 2013-2016 Red Hat Inc.
-#
-# Authors:
-#  Anthony Liguori <aliguori@us.ibm.com>
-#  Markus Armbruster <armbru@redhat.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.
+"""
+QAPI types generator
+
+Copyright IBM, Corp. 2011
+Copyright (c) 2013-2018 Red Hat Inc.
+
+Authors:
+ Anthony Liguori <aliguori@us.ibm.com>
+ Michael Roth <mdroth@linux.vnet.ibm.com>
+ Markus Armbruster <armbru@redhat.com>
+
+This work is licensed under the terms of the GNU GPL, version 2.
 # See the COPYING file in the top-level directory.
+"""
 
 from qapi import *
 
@@ -252,17 +254,11 @@ for o, a in opts:
 
 blurb = '''
  * Schema-defined QAPI types
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *  Michael Roth      <mdroth@linux.vnet.ibm.com>
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-types.c', 'qapi-types.h',
-                            blurb)
+                            blurb, __doc__)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 0a367072fb..e56b3c1256 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -1,16 +1,17 @@
-#
-# QAPI visitor generator
-#
-# Copyright IBM, Corp. 2011
-# Copyright (C) 2014-2016 Red Hat, Inc.
-#
-# Authors:
-#  Anthony Liguori <aliguori@us.ibm.com>
-#  Michael Roth    <mdroth@linux.vnet.ibm.com>
-#  Markus Armbruster <armbru@redhat.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2.
-# See the COPYING file in the top-level directory.
+"""
+QAPI visitor generator
+
+Copyright IBM, Corp. 2011
+Copyright (C) 2014-2018 Red Hat, Inc.
+
+Authors:
+ Anthony Liguori <aliguori@us.ibm.com>
+ Michael Roth    <mdroth@linux.vnet.ibm.com>
+ Markus Armbruster <armbru@redhat.com>
+
+This work is licensed under the terms of the GNU GPL, version 2.
+See the COPYING file in the top-level directory.
+"""
 
 from qapi import *
 
@@ -336,16 +337,11 @@ for o, a in opts:
 
 blurb = '''
  * Schema-defined QAPI visitors
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
 '''
 
 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
                             'qapi-visit.c', 'qapi-visit.h',
-                            blurb)
+                            blurb, __doc__)
 
 fdef.write(mcgen('''
 #include "qemu/osdep.h"
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 2e5a1ce6a8..26c45cee34 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1985,21 +1985,24 @@ def parse_command_line(extra_options='', extra_long_options=[]):
 #
 
 
-def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb):
+def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
     guard = guardname(prefix + h_file)
     c_file = output_dir + prefix + c_file
     h_file = output_dir + prefix + h_file
+    copyright = '\n * '.join(re.findall(r'^Copyright .*', doc, re.MULTILINE))
     comment = mcgen('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
 
 /*
 %(blurb)s
  *
+ * %(copyright)s
+ *
  * 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.
  */
 
 ''',
-                    blurb=blurb.strip('\n'))
+                    blurb=blurb.strip('\n'), copyright=copyright)
 
     if output_dir:
         try:
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (2 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 16:59   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc Markus Armbruster
                   ` (27 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Rename the variable holding the QAPISchemaGenFOOVisitor from gen to
vis, to avoid confusion in the next commit.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi-commands.py   | 8 ++++----
 scripts/qapi-event.py      | 8 ++++----
 scripts/qapi-introspect.py | 8 ++++----
 scripts/qapi-types.py      | 8 ++++----
 scripts/qapi-visit.py      | 8 ++++----
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 84a980d882..c3aa52fce1 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -291,9 +291,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
                   prefix=prefix, c_prefix=c_name(prefix, protect=False)))
 
 schema = QAPISchema(input_file)
-gen = QAPISchemaGenCommandVisitor()
-schema.visit(gen)
-fdef.write(gen.defn)
-fdecl.write(gen.decl)
+vis = QAPISchemaGenCommandVisitor()
+schema.visit(vis)
+fdef.write(vis.defn)
+fdecl.write(vis.decl)
 
 close_output(fdef, fdecl)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 0a098803e2..edb9ddb650 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -203,9 +203,9 @@ fdecl.write(mcgen('''
 event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
 
 schema = QAPISchema(input_file)
-gen = QAPISchemaGenEventVisitor()
-schema.visit(gen)
-fdef.write(gen.defn)
-fdecl.write(gen.decl)
+vis = QAPISchemaGenEventVisitor()
+schema.visit(vis)
+fdef.write(vis.defn)
+fdecl.write(vis.decl)
 
 close_output(fdef, fdecl)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index bd9253a172..ebe8706f41 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -193,9 +193,9 @@ fdef.write(mcgen('''
                  prefix=prefix))
 
 schema = QAPISchema(input_file)
-gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
-schema.visit(gen)
-fdef.write(gen.defn)
-fdecl.write(gen.decl)
+vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
+schema.visit(vis)
+fdef.write(vis.defn)
+fdecl.write(vis.decl)
 
 close_output(fdef, fdecl)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 1103dbda2d..4db8424da1 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -273,9 +273,9 @@ fdecl.write(mcgen('''
 '''))
 
 schema = QAPISchema(input_file)
-gen = QAPISchemaGenTypeVisitor()
-schema.visit(gen)
-fdef.write(gen.defn)
-fdecl.write(gen.decl)
+vis = QAPISchemaGenTypeVisitor()
+schema.visit(vis)
+fdef.write(vis.defn)
+fdecl.write(vis.decl)
 
 close_output(fdef, fdecl)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index e56b3c1256..3c1a0e2544 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -360,9 +360,9 @@ fdecl.write(mcgen('''
                   prefix=prefix))
 
 schema = QAPISchema(input_file)
-gen = QAPISchemaGenVisitVisitor()
-schema.visit(gen)
-fdef.write(gen.defn)
-fdecl.write(gen.decl)
+vis = QAPISchemaGenVisitVisitor()
+schema.visit(vis)
+fdef.write(vis.defn)
+fdecl.write(vis.decl)
 
 close_output(fdef, fdecl)
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (3 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-17  0:59   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some Markus Armbruster
                   ` (26 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

These classes encapsulate accumulating and writing output.

Convert C code generation to QAPIGenC and QAPIGenH.  The conversion is
rather shallow: most of the output accumulation is not converted.
Left for later.

The indentation machinery uses a single global variable indent_level,
even though we generally interleave creation of a .c and its .h.  It
should become instance variable of QAPIGenC.  Also left for later.

Documentation generation isn't converted, and QAPIGenDoc isn't used.
This will change shortly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py   | 23 +++++------
 scripts/qapi-event.py      | 22 ++++++-----
 scripts/qapi-introspect.py | 18 +++++----
 scripts/qapi-types.py      | 22 ++++++-----
 scripts/qapi-visit.py      | 22 ++++++-----
 scripts/qapi.py            | 99 +++++++++++++++++++++++++---------------------
 6 files changed, 112 insertions(+), 94 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index c3aa52fce1..8d38ade076 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -260,12 +260,10 @@ blurb = '''
  * Schema-defined QAPI/QMP commands
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qmp-marshal.c', 'qmp-commands.h',
-                            blurb, __doc__)
-
-fdef.write(mcgen('''
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/module.h"
@@ -280,20 +278,23 @@ fdef.write(mcgen('''
 #include "%(prefix)sqmp-commands.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "%(prefix)sqapi-types.h"
 #include "qapi/qmp/dispatch.h"
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-                  prefix=prefix, c_prefix=c_name(prefix, protect=False)))
+               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenCommandVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qmp-marshal.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qmp-commands.h')
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index edb9ddb650..bd7a9be3dc 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -176,11 +176,10 @@ blurb = '''
  * Schema-defined QAPI/QMP events
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-event.c', 'qapi-event.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "%(prefix)sqapi-event.h"
@@ -191,21 +190,24 @@ fdef.write(mcgen('''
 #include "qapi/qmp-event.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                  prefix=prefix))
+               prefix=prefix))
 
 event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenEventVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-event.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-event.h')
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index ebe8706f41..3d65690fe3 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -181,21 +181,23 @@ blurb = '''
  * QAPI/QMP schema introspection
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qmp-introspect.c', 'qmp-introspect.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "%(prefix)sqmp-introspect.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qmp-introspect.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qmp-introspect.h')
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 4db8424da1..c0ac879beb 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -180,7 +180,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.decl = ''
         self.defn = ''
         self._fwdecl = ''
-        self._btin = guardstart('QAPI_TYPES_BUILTIN')
+        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
 
     def visit_end(self):
         self.decl = self._fwdecl + self.decl
@@ -256,26 +256,28 @@ blurb = '''
  * Schema-defined QAPI types
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-types.c', 'qapi-types.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
 #include "%(prefix)sqapi-types.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/util.h"
 '''))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenTypeVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-types.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-types.h')
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 3c1a0e2544..888c686303 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -339,30 +339,32 @@ blurb = '''
  * Schema-defined QAPI visitors
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-visit.c', 'qapi-visit.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/visitor.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                  prefix=prefix))
+               prefix=prefix))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenVisitVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-visit.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-visit.h')
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 26c45cee34..9693fd1851 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -2,7 +2,7 @@
 # QAPI helper library
 #
 # Copyright IBM, Corp. 2011
-# Copyright (c) 2013-2016 Red Hat Inc.
+# Copyright (c) 2013-2018 Red Hat Inc.
 #
 # Authors:
 #  Anthony Liguori <aliguori@us.ibm.com>
@@ -22,10 +22,6 @@ try:
     from collections import OrderedDict
 except:
     from ordereddict import OrderedDict
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import StringIO
 
 builtin_types = {
     'null':     'QTYPE_QNULL',
@@ -1831,7 +1827,6 @@ def guardname(filename):
 
 def guardstart(name):
     return mcgen('''
-
 #ifndef %(name)s
 #define %(name)s
 
@@ -1843,7 +1838,6 @@ def guardend(name):
     return mcgen('''
 
 #endif /* %(name)s */
-
 ''',
                  name=guardname(name))
 
@@ -1980,17 +1974,53 @@ def parse_command_line(extra_options='', extra_long_options=[]):
 
     return (fname, output_dir, do_c, do_h, prefix, extra_opts)
 
+
 #
-# Generate output files with boilerplate
+# Accumulate and write output
 #
 
+class QAPIGen(object):
+
+    def __init__(self):
+        self._preamble = ''
+        self._body = ''
+
+    def preamble_add(self, text):
+        self._preamble += text
+
+    def add(self, text):
+        self._body += text
+
+    def _top(self, fname):
+        return ''
+
+    def _bottom(self, fname):
+        return ''
+
+    def write(self, output_dir, fname):
+        if output_dir:
+            try:
+                os.makedirs(output_dir)
+            except os.error as e:
+                if e.errno != errno.EEXIST:
+                    raise
+        f = open(os.path.join(output_dir, fname), 'w')
+        f.write(self._top(fname) + self._preamble + self._body
+                + self._bottom(fname))
+        f.close()
+
+
+class QAPIGenC(QAPIGen):
+
+    def __init__(self, blurb, pydoc):
+        QAPIGen.__init__(self)
+        self._blurb = blurb.strip('\n')
+        self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
+                                                  re.MULTILINE))
 
-def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
-    guard = guardname(prefix + h_file)
-    c_file = output_dir + prefix + c_file
-    h_file = output_dir + prefix + h_file
-    copyright = '\n * '.join(re.findall(r'^Copyright .*', doc, re.MULTILINE))
-    comment = mcgen('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+    def _top(self, fname):
+        return mcgen('''
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
 
 /*
 %(blurb)s
@@ -2002,40 +2032,19 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
  */
 
 ''',
-                    blurb=blurb.strip('\n'), copyright=copyright)
+                     blurb=self._blurb, copyright=self._copyright)
 
-    if output_dir:
-        try:
-            os.makedirs(output_dir)
-        except os.error as e:
-            if e.errno != errno.EEXIST:
-                raise
 
-    def maybe_open(really, name, opt):
-        if really:
-            return open(name, opt)
-        else:
-            return StringIO()
+class QAPIGenH(QAPIGenC):
 
-    fdef = maybe_open(do_c, c_file, 'w')
-    fdecl = maybe_open(do_h, h_file, 'w')
+    def _top(self, fname):
+        return QAPIGenC._top(self, fname) + guardstart(fname)
 
-    fdef.write(comment)
-    fdecl.write(comment)
-    fdecl.write(mcgen('''
-#ifndef %(guard)s
-#define %(guard)s
+    def _bottom(self, fname):
+        return guardend(fname)
 
-''',
-                      guard=guard))
 
-    return (fdef, fdecl)
-
-
-def close_output(fdef, fdecl):
-    fdecl.write(mcgen('''
-
-#endif
-'''))
-    fdecl.close()
-    fdef.close()
+class QAPIGenDoc(QAPIGen):
+    def _top(self, fname):
+        return (QAPIGen._top(self, fname)
+                + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (4 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-17  1:22   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
                   ` (25 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

In preparation of the next commit, which will turn the generators into
modules.  These global variables will become local to main() then.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py   |  9 +++++----
 scripts/qapi-event.py      | 15 +++++++--------
 scripts/qapi-introspect.py |  7 ++++---
 scripts/qapi-types.py      | 17 +++++++++--------
 scripts/qapi-visit.py      | 17 +++++++++--------
 5 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 8d38ade076..e97e16e828 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -207,7 +207,7 @@ def gen_register_command(name, success_response):
     return ret
 
 
-def gen_registry(registry):
+def gen_registry(registry, prefix):
     ret = mcgen('''
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
@@ -224,7 +224,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
 
 
 class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
-    def __init__(self):
+    def __init__(self, prefix):
+        self._prefix = prefix
         self.decl = None
         self.defn = None
         self._regy = None
@@ -237,7 +238,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._visited_ret_types = set()
 
     def visit_end(self):
-        self.defn += gen_registry(self._regy)
+        self.defn += gen_registry(self._regy, self._prefix)
         self._regy = None
         self._visited_ret_types = None
 
@@ -289,7 +290,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
                prefix=prefix, c_prefix=c_name(prefix, protect=False)))
 
 schema = QAPISchema(input_file)
-vis = QAPISchemaGenCommandVisitor()
+vis = QAPISchemaGenCommandVisitor(prefix)
 schema.visit(vis)
 genc.add(vis.defn)
 genh.add(vis.decl)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index bd7a9be3dc..3f98e2491a 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -58,7 +58,7 @@ def gen_param_var(typ):
     return ret
 
 
-def gen_event_send(name, arg_type, boxed):
+def gen_event_send(name, arg_type, boxed, event_enum_name):
     # FIXME: Our declaration of local variables (and of 'errp' in the
     # parameter list) can collide with exploded members of the event's
     # data type passed in as parameters.  If this collision ever hits in
@@ -149,7 +149,8 @@ out:
 
 
 class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
-    def __init__(self):
+    def __init__(self, prefix):
+        self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
         self.decl = None
         self.defn = None
         self._event_names = None
@@ -160,13 +161,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self._event_names = []
 
     def visit_end(self):
-        self.decl += gen_enum(event_enum_name, self._event_names)
-        self.defn += gen_enum_lookup(event_enum_name, self._event_names)
+        self.decl += gen_enum(self._enum_name, self._event_names)
+        self.defn += gen_enum_lookup(self._enum_name, self._event_names)
         self._event_names = None
 
     def visit_event(self, name, info, arg_type, boxed):
         self.decl += gen_event_send_decl(name, arg_type, boxed)
-        self.defn += gen_event_send(name, arg_type, boxed)
+        self.defn += gen_event_send(name, arg_type, boxed, self._enum_name)
         self._event_names.append(name)
 
 
@@ -199,10 +200,8 @@ genh.add(mcgen('''
 ''',
                prefix=prefix))
 
-event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
-
 schema = QAPISchema(input_file)
-vis = QAPISchemaGenEventVisitor()
+vis = QAPISchemaGenEventVisitor(prefix)
 schema.visit(vis)
 genc.add(vis.defn)
 genh.add(vis.decl)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 3d65690fe3..2418b80a82 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -41,7 +41,8 @@ def to_c_string(string):
 
 
 class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
-    def __init__(self, unmask):
+    def __init__(self, prefix, unmask):
+        self._prefix = prefix
         self._unmask = unmask
         self.defn = None
         self.decl = None
@@ -65,7 +66,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
         # generate C
         # TODO can generate awfully long lines
         jsons.extend(self._jsons)
-        name = c_name(prefix, protect=False) + 'qmp_schema_json'
+        name = c_name(self._prefix, protect=False) + 'qmp_schema_json'
         self.decl = mcgen('''
 extern const char %(c_name)s[];
 ''',
@@ -192,7 +193,7 @@ genc.add(mcgen('''
                prefix=prefix))
 
 schema = QAPISchema(input_file)
-vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
+vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
 schema.visit(vis)
 genc.add(vis.defn)
 genh.add(vis.decl)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index c0ac879beb..5ff2bfcf41 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -168,7 +168,8 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
 
 
 class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
-    def __init__(self):
+    def __init__(self, opt_builtins):
+        self._opt_builtins = opt_builtins
         self.decl = None
         self.defn = None
         self._fwdecl = None
@@ -187,7 +188,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self._fwdecl = None
         # To avoid header dependency hell, we always generate
         # declarations for built-in types in our header files and
-        # simply guard them.  See also do_builtins (command line
+        # simply guard them.  See also opt_builtins (command line
         # option -b).
         self._btin += guardend('QAPI_TYPES_BUILTIN')
         self.decl = self._btin + self.decl
@@ -202,7 +203,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         # TODO use something cleaner than existence of info
         if not info:
             self._btin += gen_enum(name, values, prefix)
-            if do_builtins:
+            if self._opt_builtins:
                 self.defn += gen_enum_lookup(name, values, prefix)
         else:
             self._fwdecl += gen_enum(name, values, prefix)
@@ -213,7 +214,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
             self._btin += gen_fwd_object_or_array(name)
             self._btin += gen_array(name, element_type)
             self._btin += gen_type_cleanup_decl(name)
-            if do_builtins:
+            if self._opt_builtins:
                 self.defn += gen_type_cleanup(name)
         else:
             self._fwdecl += gen_fwd_object_or_array(name)
@@ -241,16 +242,16 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
 
 # If you link code generated from multiple schemata, you want only one
 # instance of the code for built-in types.  Generate it only when
-# do_builtins, enabled by command line option -b.  See also
+# opt_builtins, enabled by command line option -b.  See also
 # QAPISchemaGenTypeVisitor.visit_end().
-do_builtins = False
+opt_builtins = False
 
 (input_file, output_dir, do_c, do_h, prefix, opts) = \
     parse_command_line('b', ['builtins'])
 
 for o, a in opts:
     if o in ('-b', '--builtins'):
-        do_builtins = True
+        opt_builtins = True
 
 blurb = '''
  * Schema-defined QAPI types
@@ -272,7 +273,7 @@ genh.add(mcgen('''
 '''))
 
 schema = QAPISchema(input_file)
-vis = QAPISchemaGenTypeVisitor()
+vis = QAPISchemaGenTypeVisitor(opt_builtins)
 schema.visit(vis)
 genc.add(vis.defn)
 genh.add(vis.decl)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 888c686303..0a1eff7736 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -264,7 +264,8 @@ out:
 
 
 class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
-    def __init__(self):
+    def __init__(self, opt_builtins):
+        self._opt_builtins = opt_builtins
         self.decl = None
         self.defn = None
         self._btin = None
@@ -277,7 +278,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
     def visit_end(self):
         # To avoid header dependency hell, we always generate
         # declarations for built-in types in our header files and
-        # simply guard them.  See also do_builtins (command line
+        # simply guard them.  See also opt_builtins (command line
         # option -b).
         self._btin += guardend('QAPI_VISIT_BUILTIN')
         self.decl = self._btin + self.decl
@@ -288,7 +289,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         # TODO use something cleaner than existence of info
         if not info:
             self._btin += gen_visit_decl(name, scalar=True)
-            if do_builtins:
+            if self._opt_builtins:
                 self.defn += gen_visit_enum(name)
         else:
             self.decl += gen_visit_decl(name, scalar=True)
@@ -299,7 +300,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         defn = gen_visit_list(name, element_type)
         if isinstance(element_type, QAPISchemaBuiltinType):
             self._btin += decl
-            if do_builtins:
+            if self._opt_builtins:
                 self.defn += defn
         else:
             self.decl += decl
@@ -324,16 +325,16 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
 
 # If you link code generated from multiple schemata, you want only one
 # instance of the code for built-in types.  Generate it only when
-# do_builtins, enabled by command line option -b.  See also
+# opt_builtins, enabled by command line option -b.  See also
 # QAPISchemaGenVisitVisitor.visit_end().
-do_builtins = False
+opt_builtins = False
 
 (input_file, output_dir, do_c, do_h, prefix, opts) = \
     parse_command_line('b', ['builtins'])
 
 for o, a in opts:
     if o in ('-b', '--builtins'):
-        do_builtins = True
+        opt_builtins = True
 
 blurb = '''
  * Schema-defined QAPI visitors
@@ -359,7 +360,7 @@ genh.add(mcgen('''
                prefix=prefix))
 
 schema = QAPISchema(input_file)
-vis = QAPISchemaGenVisitVisitor()
+vis = QAPISchemaGenVisitVisitor(opt_builtins)
 schema.visit(vis)
 genc.add(vis.defn)
 genh.add(vis.decl)
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (5 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-17  1:29   ` Michael Roth
  2018-02-27 15:53   ` Eric Blake
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
                   ` (24 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The next commit will introduce a common driver program for all
generators.  The generators need to be modules for that.  qapi2texi.py
already is.  Make the other generators follow suit.

The changes are actually trivial.  Obvious in the diffs once you view
them with whitespace changes ignored.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py   | 43 ++++++++++++++++++--------------
 scripts/qapi-event.py      | 43 ++++++++++++++++++--------------
 scripts/qapi-introspect.py | 54 ++++++++++++++++++++++------------------
 scripts/qapi-types.py      | 56 ++++++++++++++++++++++-------------------
 scripts/qapi-visit.py      | 62 +++++++++++++++++++++++++---------------------
 5 files changed, 143 insertions(+), 115 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index e97e16e828..8584cb5873 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -255,16 +255,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._regy += gen_register_command(name, success_response)
 
 
-(input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
+def main(argv):
+    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
 
-blurb = '''
+    blurb = '''
  * Schema-defined QAPI/QMP commands
 '''
 
-genc = QAPIGenC(blurb, __doc__)
-genh = QAPIGenH(blurb, __doc__)
+    genc = QAPIGenC(blurb, __doc__)
+    genh = QAPIGenH(blurb, __doc__)
 
-genc.add(mcgen('''
+    genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/module.h"
@@ -279,23 +280,27 @@ genc.add(mcgen('''
 #include "%(prefix)sqmp-commands.h"
 
 ''',
-               prefix=prefix))
+                   prefix=prefix))
 
-genh.add(mcgen('''
+    genh.add(mcgen('''
 #include "%(prefix)sqapi-types.h"
 #include "qapi/qmp/dispatch.h"
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
-
-schema = QAPISchema(input_file)
-vis = QAPISchemaGenCommandVisitor(prefix)
-schema.visit(vis)
-genc.add(vis.defn)
-genh.add(vis.decl)
-
-if do_c:
-    genc.write(output_dir, prefix + 'qmp-marshal.c')
-if do_h:
-    genh.write(output_dir, prefix + 'qmp-commands.h')
+                   prefix=prefix, c_prefix=c_name(prefix, protect=False)))
+
+    schema = QAPISchema(input_file)
+    vis = QAPISchemaGenCommandVisitor(prefix)
+    schema.visit(vis)
+    genc.add(vis.defn)
+    genh.add(vis.decl)
+
+    if do_c:
+        genc.write(output_dir, prefix + 'qmp-marshal.c')
+    if do_h:
+        genh.write(output_dir, prefix + 'qmp-commands.h')
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 3f98e2491a..e7e07f0055 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -171,16 +171,17 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self._event_names.append(name)
 
 
-(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
+def main(argv):
+    (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
 
-blurb = '''
+    blurb = '''
  * Schema-defined QAPI/QMP events
 '''
 
-genc = QAPIGenC(blurb, __doc__)
-genh = QAPIGenH(blurb, __doc__)
+    genc = QAPIGenC(blurb, __doc__)
+    genh = QAPIGenH(blurb, __doc__)
 
-genc.add(mcgen('''
+    genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "%(prefix)sqapi-event.h"
@@ -191,22 +192,26 @@ genc.add(mcgen('''
 #include "qapi/qmp-event.h"
 
 ''',
-               prefix=prefix))
+                   prefix=prefix))
 
-genh.add(mcgen('''
+    genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-               prefix=prefix))
-
-schema = QAPISchema(input_file)
-vis = QAPISchemaGenEventVisitor(prefix)
-schema.visit(vis)
-genc.add(vis.defn)
-genh.add(vis.decl)
-
-if do_c:
-    genc.write(output_dir, prefix + 'qapi-event.c')
-if do_h:
-    genh.write(output_dir, prefix + 'qapi-event.h')
+                   prefix=prefix))
+
+    schema = QAPISchema(input_file)
+    vis = QAPISchemaGenEventVisitor(prefix)
+    schema.visit(vis)
+    genc.add(vis.defn)
+    genh.add(vis.decl)
+
+    if do_c:
+        genc.write(output_dir, prefix + 'qapi-event.c')
+    if do_h:
+        genh.write(output_dir, prefix + 'qapi-event.h')
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 2418b80a82..b098b95053 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -167,38 +167,44 @@ const char %(c_name)s[] = %(c_string)s;
         arg_type = arg_type or self._schema.the_empty_object_type
         self._gen_json(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
-opt_unmask = False
 
-(input_file, output_dir, do_c, do_h, prefix, opts) = \
-    parse_command_line('u', ['unmask-non-abi-names'])
+def main(argv):
+    # Debugging aid: unmask QAPI schema's type names
+    # We normally mask them, because they're not QMP wire ABI
+    opt_unmask = False
 
-for o, a in opts:
-    if o in ('-u', '--unmask-non-abi-names'):
-        opt_unmask = True
+    (input_file, output_dir, do_c, do_h, prefix, opts) = \
+        parse_command_line('u', ['unmask-non-abi-names'])
 
-blurb = '''
+    for o, a in opts:
+        if o in ('-u', '--unmask-non-abi-names'):
+            opt_unmask = True
+
+    blurb = '''
  * QAPI/QMP schema introspection
 '''
 
-genc = QAPIGenC(blurb, __doc__)
-genh = QAPIGenH(blurb, __doc__)
+    genc = QAPIGenC(blurb, __doc__)
+    genh = QAPIGenH(blurb, __doc__)
 
-genc.add(mcgen('''
+    genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "%(prefix)sqmp-introspect.h"
 
 ''',
-               prefix=prefix))
-
-schema = QAPISchema(input_file)
-vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
-schema.visit(vis)
-genc.add(vis.defn)
-genh.add(vis.decl)
-
-if do_c:
-    genc.write(output_dir, prefix + 'qmp-introspect.c')
-if do_h:
-    genh.write(output_dir, prefix + 'qmp-introspect.h')
+                   prefix=prefix))
+
+    schema = QAPISchema(input_file)
+    vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
+    schema.visit(vis)
+    genc.add(vis.defn)
+    genh.add(vis.decl)
+
+    if do_c:
+        genc.write(output_dir, prefix + 'qmp-introspect.c')
+    if do_h:
+        genh.write(output_dir, prefix + 'qmp-introspect.h')
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 5ff2bfcf41..10955d1c01 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -240,45 +240,51 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.decl += gen_object(name, None, [variants.tag_member], variants)
         self._gen_type_cleanup(name)
 
-# If you link code generated from multiple schemata, you want only one
-# instance of the code for built-in types.  Generate it only when
-# opt_builtins, enabled by command line option -b.  See also
-# QAPISchemaGenTypeVisitor.visit_end().
-opt_builtins = False
 
-(input_file, output_dir, do_c, do_h, prefix, opts) = \
-    parse_command_line('b', ['builtins'])
+def main(argv):
+    # If you link code generated from multiple schemata, you want only one
+    # instance of the code for built-in types.  Generate it only when
+    # opt_builtins, enabled by command line option -b.  See also
+    # QAPISchemaGenTypeVisitor.visit_end().
+    opt_builtins = False
 
-for o, a in opts:
-    if o in ('-b', '--builtins'):
-        opt_builtins = True
+    (input_file, output_dir, do_c, do_h, prefix, opts) = \
+        parse_command_line('b', ['builtins'])
 
-blurb = '''
+    for o, a in opts:
+        if o in ('-b', '--builtins'):
+            opt_builtins = True
+
+    blurb = '''
  * Schema-defined QAPI types
 '''
 
-genc = QAPIGenC(blurb, __doc__)
-genh = QAPIGenH(blurb, __doc__)
+    genc = QAPIGenC(blurb, __doc__)
+    genh = QAPIGenH(blurb, __doc__)
 
-genc.add(mcgen('''
+    genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
 #include "%(prefix)sqapi-types.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-               prefix=prefix))
+                   prefix=prefix))
 
-genh.add(mcgen('''
+    genh.add(mcgen('''
 #include "qapi/util.h"
 '''))
 
-schema = QAPISchema(input_file)
-vis = QAPISchemaGenTypeVisitor(opt_builtins)
-schema.visit(vis)
-genc.add(vis.defn)
-genh.add(vis.decl)
+    schema = QAPISchema(input_file)
+    vis = QAPISchemaGenTypeVisitor(opt_builtins)
+    schema.visit(vis)
+    genc.add(vis.defn)
+    genh.add(vis.decl)
 
-if do_c:
-    genc.write(output_dir, prefix + 'qapi-types.c')
-if do_h:
-    genh.write(output_dir, prefix + 'qapi-types.h')
+    if do_c:
+        genc.write(output_dir, prefix + 'qapi-types.c')
+    if do_h:
+        genh.write(output_dir, prefix + 'qapi-types.h')
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 0a1eff7736..6d829c4d1d 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -323,49 +323,55 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         self.decl += gen_visit_decl(name)
         self.defn += gen_visit_alternate(name, 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
-# opt_builtins, enabled by command line option -b.  See also
-# QAPISchemaGenVisitVisitor.visit_end().
-opt_builtins = False
 
-(input_file, output_dir, do_c, do_h, prefix, opts) = \
-    parse_command_line('b', ['builtins'])
+def main(argv):
+    # If you link code generated from multiple schemata, you want only one
+    # instance of the code for built-in types.  Generate it only when
+    # opt_builtins, enabled by command line option -b.  See also
+    # QAPISchemaGenVisitVisitor.visit_end().
+    opt_builtins = False
 
-for o, a in opts:
-    if o in ('-b', '--builtins'):
-        opt_builtins = True
+    (input_file, output_dir, do_c, do_h, prefix, opts) = \
+        parse_command_line('b', ['builtins'])
 
-blurb = '''
+    for o, a in opts:
+        if o in ('-b', '--builtins'):
+            opt_builtins = True
+
+    blurb = '''
  * Schema-defined QAPI visitors
 '''
 
-genc = QAPIGenC(blurb, __doc__)
-genh = QAPIGenH(blurb, __doc__)
+    genc = QAPIGenC(blurb, __doc__)
+    genh = QAPIGenH(blurb, __doc__)
 
-genc.add(mcgen('''
+    genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-               prefix=prefix))
+                   prefix=prefix))
 
-genh.add(mcgen('''
+    genh.add(mcgen('''
 #include "qapi/visitor.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-               prefix=prefix))
-
-schema = QAPISchema(input_file)
-vis = QAPISchemaGenVisitVisitor(opt_builtins)
-schema.visit(vis)
-genc.add(vis.defn)
-genh.add(vis.decl)
-
-if do_c:
-    genc.write(output_dir, prefix + 'qapi-visit.c')
-if do_h:
-    genh.write(output_dir, prefix + 'qapi-visit.h')
+                   prefix=prefix))
+
+    schema = QAPISchema(input_file)
+    vis = QAPISchemaGenVisitVisitor(opt_builtins)
+    schema.visit(vis)
+    genc.add(vis.defn)
+    genh.add(vis.decl)
+
+    if do_c:
+        genc.write(output_dir, prefix + 'qapi-visit.c')
+    if do_h:
+        genh.write(output_dir, prefix + 'qapi-visit.h')
+
+
+if __name__ == '__main__':
+    main(sys.argv)
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (6 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:42   ` Eric Blake
  2018-02-18 22:16   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
                   ` (23 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Whenever qapi-schema.json changes, we run six programs eleven times to
update eleven files.  Similar for qga/qapi-schema.json.  This is
silly.  Replace the six programs by a single program that spits out
all eleven files.

The programs become modules in new Python package qapi, along with the
helper library.  This requires moving them to scripts/qapi/.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 .gitignore                                         |  2 +
 Makefile                                           | 86 +++++++++----------
 docs/devel/qapi-code-gen.txt                       | 97 ++++++++++------------
 monitor.c                                          |  2 +-
 qapi-schema.json                                   |  2 +-
 scripts/qapi-gen.py                                | 41 +++++++++
 scripts/qapi/__init__.py                           |  0
 scripts/{qapi-commands.py => qapi/commands.py}     | 23 ++---
 scripts/{qapi.py => qapi/common.py}                | 18 +---
 scripts/{qapi2texi.py => qapi/doc.py}              | 29 ++-----
 scripts/{qapi-event.py => qapi/events.py}          | 23 ++---
 scripts/{qapi-introspect.py => qapi/introspect.py} | 32 ++-----
 scripts/{qapi-types.py => qapi/types.py}           | 34 ++------
 scripts/{qapi-visit.py => qapi/visit.py}           | 34 ++------
 tests/Makefile.include                             | 56 ++++++-------
 tests/qapi-schema/test-qapi.py                     |  4 +-
 16 files changed, 193 insertions(+), 290 deletions(-)
 create mode 100755 scripts/qapi-gen.py
 create mode 100644 scripts/qapi/__init__.py
 rename scripts/{qapi-commands.py => qapi/commands.py} (94%)
 rename scripts/{qapi.py => qapi/common.py} (99%)
 rename scripts/{qapi2texi.py => qapi/doc.py} (92%)
 mode change 100755 => 100644
 rename scripts/{qapi-event.py => qapi/events.py} (92%)
 rename scripts/{qapi-introspect.py => qapi/introspect.py} (90%)
 rename scripts/{qapi-types.py => qapi/types.py} (90%)
 rename scripts/{qapi-visit.py => qapi/visit.py} (92%)

diff --git a/.gitignore b/.gitignore
index 704b22285d..2f9a92f6cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,9 +28,11 @@
 /linux-headers/asm
 /qga/qapi-generated
 /qapi-generated
+/qapi-gen-timestamp
 /qapi-types.[ch]
 /qapi-visit.[ch]
 /qapi-event.[ch]
+/qapi-doc.texi
 /qmp-commands.h
 /qmp-introspect.[ch]
 /qmp-marshal.c
diff --git a/Makefile b/Makefile
index 4ec7a3cb82..bd781c6aad 100644
--- a/Makefile
+++ b/Makefile
@@ -94,6 +94,7 @@ GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
 GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
 GENERATED_FILES += qmp-introspect.h
 GENERATED_FILES += qmp-introspect.c
+GENERATED_FILES += qapi-doc.texi
 
 GENERATED_FILES += trace/generated-tcg-tracers.h
 
@@ -483,25 +484,26 @@ qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated
 qemu-keymap$(EXESUF): LIBS += $(XKBCOMMON_LIBS)
 qemu-keymap$(EXESUF): QEMU_CFLAGS += $(XKBCOMMON_CFLAGS)
 
-gen-out-type = $(subst .,-,$(suffix $@))
+qapi-py = $(SRC_PATH)/scripts/qapi/commands.py \
+$(SRC_PATH)/scripts/qapi/events.py \
+$(SRC_PATH)/scripts/qapi/introspect.py \
+$(SRC_PATH)/scripts/qapi/types.py \
+$(SRC_PATH)/scripts/qapi/visit.py \
+$(SRC_PATH)/scripts/qapi/common.py \
+$(SRC_PATH)/scripts/qapi/doc.py \
+$(SRC_PATH)/scripts/ordereddict.py \
+$(SRC_PATH)/scripts/qapi-gen.py
 
-qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
-
-qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
-$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
-		"GEN","$@")
-qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
-$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
-		"GEN","$@")
-qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
-$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
-		$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
-		"GEN","$@")
+qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
+qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
+qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \
+qga/qapi-generated/qga-qapi-doc.texi: \
+qga/qapi-generated/qapi-gen-timestamp ;
+qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
+	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+		-o qga/qapi-generated -p "qga-" $<, \
+		"GEN","$(@:%-timestamp=%)")
+	@>$@
 
 qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
@@ -518,31 +520,18 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/transaction.json \
                $(SRC_PATH)/qapi/ui.json
 
-qapi-types.c qapi-types.h :\
-$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
-		$(gen-out-type) -o "." -b $<, \
-		"GEN","$@")
-qapi-visit.c qapi-visit.h :\
-$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
-		$(gen-out-type) -o "." -b $<, \
-		"GEN","$@")
-qapi-event.c qapi-event.h :\
-$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-event.py \
-		$(gen-out-type) -o "." $<, \
-		"GEN","$@")
-qmp-commands.h qmp-marshal.c :\
-$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
-		$(gen-out-type) -o "." $<, \
-		"GEN","$@")
-qmp-introspect.h qmp-introspect.c :\
-$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-introspect.py \
-		$(gen-out-type) -o "." $<, \
-		"GEN","$@")
+qapi-types.c qapi-types.h \
+qapi-visit.c qapi-visit.h \
+qmp-commands.h qmp-marshal.c \
+qapi-event.c qapi-event.h \
+qmp-introspect.h qmp-introspect.c \
+qapi-doc.texi: \
+qapi-gen-timestamp ;
+qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
+	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
+		-o "." -b $<, \
+		"GEN","$(@:%-timestamp=%)")
+	@>$@
 
 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
 $(qga-obj-y): $(QGALIB_GEN)
@@ -602,6 +591,7 @@ clean:
 	rm -f trace/generated-tracers-dtrace.dtrace*
 	rm -f trace/generated-tracers-dtrace.h*
 	rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
+	rm -f qapi-gen-timestamp
 	rm -rf qapi-generated
 	rm -rf qga/qapi-generated
 	for d in $(ALL_SUBDIRS); do \
@@ -810,13 +800,11 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
 
-docs/interop/qemu-qmp-qapi.texi docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
+docs/interop/qemu-qmp-qapi.texi: qapi-doc.texi
+	@cp -p $< $@
 
-docs/interop/qemu-qmp-qapi.texi: $(qapi-modules)
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
-
-docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json
-	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
+docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi
+	@cp -p $< $@
 
 qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
 qemu.1: qemu-option-trace.texi
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 5900b39b91..1a1cbaea7b 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -899,12 +899,13 @@ the names of built-in types.  Clients should examine member
 
 == Code generation ==
 
-Schemas are fed into five scripts to generate all the code/files that,
-paired with the core QAPI libraries, comprise everything required to
-take JSON commands read in by a Client JSON Protocol server, unmarshal
-the arguments into the underlying C types, call into the corresponding
-C function, map the response back to a Client JSON Protocol response
-to be returned to the user, and introspect the commands.
+The QAPI code generator qapi-gen.py generates code and documentation
+from the schema.  Together with the core QAPI libraries, this code
+provides everything required to take JSON commands read in by a Client
+JSON Protocol server, unmarshal the arguments into the underlying C
+types, call into the corresponding C function, map the response back
+to a Client JSON Protocol response to be returned to the user, and
+introspect the commands.
 
 As an example, we'll use the following schema, which describes a
 single complex user-defined type, along with command which takes a
@@ -922,18 +923,23 @@ qmp_my_command(); everything else is produced by the generator.
 
     { 'event': 'MY_EVENT' }
 
+We run qapi-gen.py like this:
+
+    $ python scripts/qapi-gen.py --output-dir="qapi-generated" \
+    --prefix="example-" example-schema.json
+
 For a more thorough look at generated code, the testsuite includes
 tests/qapi-schema/qapi-schema-tests.json that covers more examples of
 what the generator will accept, and compiles the resulting C code as
 part of 'make check-unit'.
 
-=== scripts/qapi-types.py ===
+=== Code generated for QAPI types ===
 
-Used to generate the C types defined by a schema, along with
-supporting code. The following files are created:
+The following files are created:
 
 $(prefix)qapi-types.h - C types corresponding to types defined in
-                        the schema you pass in
+                        the schema
+
 $(prefix)qapi-types.c - Cleanup functions for the above C types
 
 The $(prefix) is an optional parameter used as a namespace to keep the
@@ -943,8 +949,6 @@ created code.
 
 Example:
 
-    $ python scripts/qapi-types.py --output-dir="qapi-generated" \
-    --prefix="example-" example-schema.json
     $ cat qapi-generated/example-qapi-types.h
 [Uninteresting stuff omitted...]
 
@@ -1008,28 +1012,26 @@ Example:
         visit_free(v);
     }
 
-=== scripts/qapi-visit.py ===
+=== Code generated for visiting QAPI types ===
 
-Used to generate the visitor functions used to walk through and
-convert between a native QAPI C data structure and some other format
-(such as QObject); the generated functions are named visit_type_FOO()
-and visit_type_FOO_members().
+These are the visitor functions used to walk through and convert
+between a native QAPI C data structure and some other format (such as
+QObject); the generated functions are named visit_type_FOO() and
+visit_type_FOO_members().
 
 The following files are generated:
 
-$(prefix)qapi-visit.c: visitor function for a particular C type, used
+$(prefix)qapi-visit.c: Visitor function for a particular C type, used
                        to automagically convert QObjects into the
                        corresponding C type and vice-versa, as well
                        as for deallocating memory for an existing C
                        type
 
-$(prefix)qapi-visit.h: declarations for previously mentioned visitor
+$(prefix)qapi-visit.h: Declarations for previously mentioned visitor
                        functions
 
 Example:
 
-    $ python scripts/qapi-visit.py --output-dir="qapi-generated"
-    --prefix="example-" example-schema.json
     $ cat qapi-generated/example-qapi-visit.h
 [Uninteresting stuff omitted...]
 
@@ -1137,30 +1139,22 @@ Example:
         error_propagate(errp, err);
     }
 
-=== scripts/qapi-commands.py ===
+=== Code generated for commands ===
 
-Used to generate the marshaling/dispatch functions for the commands
-defined in the schema. The generated code implements
-qmp_marshal_COMMAND() (registered automatically), and declares
-qmp_COMMAND() that the user must implement.  The following files are
-generated:
+These are the marshaling/dispatch functions for the commands defined
+in the schema.  The generated code provides qmp_marshal_COMMAND(), and
+declares qmp_COMMAND() that the user must implement.
 
-$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
-                        QMP command defined in the schema. Functions
-                        generated by qapi-visit.py are used to
-                        convert QObjects received from the wire into
-                        function parameters, and uses the same
-                        visitor functions to convert native C return
-                        values to QObjects from transmission back
-                        over the wire.
+The following files are generated:
+
+$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each
+                        QMP command defined in the schema
 
 $(prefix)qmp-commands.h: Function prototypes for the QMP commands
-                         specified in the schema.
+                         specified in the schema
 
 Example:
 
-    $ python scripts/qapi-commands.py --output-dir="qapi-generated"
-    --prefix="example-" example-schema.json
     $ cat qapi-generated/example-qmp-commands.h
 [Uninteresting stuff omitted...]
 
@@ -1242,20 +1236,20 @@ Example:
                              qmp_marshal_my_command, QCO_NO_OPTIONS);
     }
 
-=== scripts/qapi-event.py ===
+=== Code generated for events ===
 
-Used to generate the event-related C code defined by a schema, with
-implementations for qapi_event_send_FOO(). The following files are
-created:
+This is the code related to events defined in the schema, providing
+qapi_event_send_EVENT().
+
+The following files are created:
 
 $(prefix)qapi-event.h - Function prototypes for each event type, plus an
                         enumeration of all event names
+
 $(prefix)qapi-event.c - Implementation of functions to send an event
 
 Example:
 
-    $ python scripts/qapi-event.py --output-dir="qapi-generated"
-    --prefix="example-" example-schema.json
     $ cat qapi-generated/example-qapi-event.h
 [Uninteresting stuff omitted...]
 
@@ -1302,23 +1296,22 @@ Example:
     }
 
     const char *const example_QAPIEvent_lookup[] = {
-        [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
+
+[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
         [EXAMPLE_QAPI_EVENT__MAX] = NULL,
     };
 
-=== scripts/qapi-introspect.py ===
+=== Code generated for introspection ===
 
-Used to generate the introspection C code for a schema. The following
-files are created:
+The following files are created:
 
 $(prefix)qmp-introspect.c - Defines a string holding a JSON
-                            description of the schema.
-$(prefix)qmp-introspect.h - Declares the above string.
+                            description of the schema
+
+$(prefix)qmp-introspect.h - Declares the above string
 
 Example:
 
-    $ python scripts/qapi-introspect.py --output-dir="qapi-generated"
-    --prefix="example-" example-schema.json
     $ cat qapi-generated/example-qmp-introspect.h
 [Uninteresting stuff omitted...]
 
diff --git a/monitor.c b/monitor.c
index f4992505b1..df670f3e15 100644
--- a/monitor.c
+++ b/monitor.c
@@ -951,7 +951,7 @@ EventInfoList *qmp_query_events(Error **errp)
  * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it
  * to QObject with generated output marshallers, every time.  Instead,
  * we do it in test-qobject-input-visitor.c, just to make sure
- * qapi-introspect.py's output actually conforms to the schema.
+ * qapi-gen.py's output actually conforms to the schema.
  */
 static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
                                  Error **errp)
diff --git a/qapi-schema.json b/qapi-schema.json
index 5c06745c79..0d651c8399 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -72,7 +72,7 @@
         'q_obj_CpuInfo-base'    # CPU, visible through query-cpu
     ] } }
 
-# Documentation generated with qapi2texi.py is in source order, with
+# Documentation generated with qapi-gen.py is in source order, with
 # included sub-schemas inserted at the first include directive
 # (subsequent include directives have no effect).  To get a sane and
 # stable order, it's best to include each sub-schema just once, or
diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
new file mode 100755
index 0000000000..2100ca1145
--- /dev/null
+++ b/scripts/qapi-gen.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# QAPI generator
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+import sys
+from qapi.common import parse_command_line, QAPISchema
+from qapi.types import gen_types
+from qapi.visit import gen_visit
+from qapi.commands import gen_commands
+from qapi.events import gen_events
+from qapi.introspect import gen_introspect
+from qapi.doc import gen_doc
+
+
+def main(argv):
+    (input_file, output_dir, prefix, opts) = \
+        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
+
+    opt_builtins = False
+    opt_unmask = False
+
+    for o, a in opts:
+        if o in ('-b', '--builtins'):
+            opt_builtins = True
+        if o in ('-u', '--unmask-non-abi-names'):
+            opt_unmask = True
+
+    schema = QAPISchema(input_file)
+
+    gen_types(schema, output_dir, prefix, opt_builtins)
+    gen_visit(schema, output_dir, prefix, opt_builtins)
+    gen_commands(schema, output_dir, prefix)
+    gen_events(schema, output_dir, prefix)
+    gen_introspect(schema, output_dir, prefix, opt_unmask)
+    gen_doc(schema, output_dir, prefix)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/scripts/qapi/__init__.py b/scripts/qapi/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/scripts/qapi-commands.py b/scripts/qapi/commands.py
similarity index 94%
rename from scripts/qapi-commands.py
rename to scripts/qapi/commands.py
index 8584cb5873..a744611d58 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi/commands.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
 See the COPYING file in the top-level directory.
 """
 
-from qapi import *
+from qapi.common import *
 
 
 def gen_command_decl(name, arg_type, boxed, ret_type):
@@ -255,13 +255,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
         self._regy += gen_register_command(name, success_response)
 
 
-def main(argv):
-    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
-
-    blurb = '''
- * Schema-defined QAPI/QMP commands
-'''
-
+def gen_commands(schema, output_dir, prefix):
+    blurb = ' * Schema-defined QAPI/QMP commands'
     genc = QAPIGenC(blurb, __doc__)
     genh = QAPIGenH(blurb, __doc__)
 
@@ -290,17 +285,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
                    prefix=prefix, c_prefix=c_name(prefix, protect=False)))
 
-    schema = QAPISchema(input_file)
     vis = QAPISchemaGenCommandVisitor(prefix)
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-
-    if do_c:
-        genc.write(output_dir, prefix + 'qmp-marshal.c')
-    if do_h:
-        genh.write(output_dir, prefix + 'qmp-commands.h')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+    genc.write(output_dir, prefix + 'qmp-marshal.c')
+    genh.write(output_dir, prefix + 'qmp-commands.h')
diff --git a/scripts/qapi.py b/scripts/qapi/common.py
similarity index 99%
rename from scripts/qapi.py
rename to scripts/qapi/common.py
index 9693fd1851..868ec25deb 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi/common.py
@@ -1932,17 +1932,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
 
     try:
         opts, args = getopt.gnu_getopt(sys.argv[1:],
-                                       'chp:o:' + extra_options,
-                                       ['source', 'header', 'prefix=',
-                                        'output-dir='] + extra_long_options)
+                                       'p:o:' + extra_options,
+                                       ['prefix=', 'output-dir=']
+                                       + extra_long_options)
     except getopt.GetoptError as err:
         print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
         sys.exit(1)
 
     output_dir = ''
     prefix = ''
-    do_c = False
-    do_h = False
     extra_opts = []
 
     for oa in opts:
@@ -1956,23 +1954,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
             prefix = a
         elif o in ('-o', '--output-dir'):
             output_dir = a + '/'
-        elif o in ('-c', '--source'):
-            do_c = True
-        elif o in ('-h', '--header'):
-            do_h = True
         else:
             extra_opts.append(oa)
 
-    if not do_c and not do_h:
-        do_c = True
-        do_h = True
-
     if len(args) != 1:
         print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
         sys.exit(1)
     fname = args[0]
 
-    return (fname, output_dir, do_c, do_h, prefix, extra_opts)
+    return (fname, output_dir, prefix, extra_opts)
 
 
 #
diff --git a/scripts/qapi2texi.py b/scripts/qapi/doc.py
old mode 100755
new mode 100644
similarity index 92%
rename from scripts/qapi2texi.py
rename to scripts/qapi/doc.py
index 8a604d86a6..cc4d5a43fb
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi/doc.py
@@ -4,11 +4,10 @@
 # This work is licensed under the terms of the GNU LGPL, version 2+.
 # See the COPYING file in the top-level directory.
 """This script produces the documentation of a qapi schema in texinfo format"""
+
 from __future__ import print_function
 import re
-import sys
-
-import qapi
+import qapi.common
 
 MSG_FMT = """
 @deftypefn {type} {{}} {name}
@@ -197,7 +196,7 @@ def texi_entity(doc, what, base=None, variants=None,
             + texi_sections(doc))
 
 
-class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
+class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
     def __init__(self):
         self.out = None
         self.cur_doc = None
@@ -272,20 +271,8 @@ def texi_schema(schema):
     return gen.out
 
 
-def main(argv):
-    """Takes schema argument, prints result to stdout"""
-    if len(argv) != 2:
-        print("%s: need exactly 1 argument: SCHEMA" % argv[0], file=sys.stderr)
-        sys.exit(1)
-
-    schema = qapi.QAPISchema(argv[1])
-    if not qapi.doc_required:
-        print("%s: need pragma 'doc-required' "
-               "to generate documentation" % argv[0], file=sys.stderr)
-        sys.exit(1)
-    print('@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n')
-    print(texi_schema(schema), end='')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+def gen_doc(schema, output_dir, prefix):
+    if qapi.common.doc_required:
+        gen = qapi.common.QAPIGenDoc()
+        gen.add(texi_schema(schema))
+        gen.write(output_dir, prefix + 'qapi-doc.texi')
diff --git a/scripts/qapi-event.py b/scripts/qapi/events.py
similarity index 92%
rename from scripts/qapi-event.py
rename to scripts/qapi/events.py
index e7e07f0055..b7dc82004f 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi/events.py
@@ -12,7 +12,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
 See the COPYING file in the top-level directory.
 """
 
-from qapi import *
+from qapi.common import *
 
 
 def build_event_send_proto(name, arg_type, boxed):
@@ -171,13 +171,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
         self._event_names.append(name)
 
 
-def main(argv):
-    (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
-
-    blurb = '''
- * Schema-defined QAPI/QMP events
-'''
-
+def gen_events(schema, output_dir, prefix):
+    blurb = ' * Schema-defined QAPI/QMP events'
     genc = QAPIGenC(blurb, __doc__)
     genh = QAPIGenH(blurb, __doc__)
 
@@ -201,17 +196,9 @@ def main(argv):
 ''',
                    prefix=prefix))
 
-    schema = QAPISchema(input_file)
     vis = QAPISchemaGenEventVisitor(prefix)
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-
-    if do_c:
-        genc.write(output_dir, prefix + 'qapi-event.c')
-    if do_h:
-        genh.write(output_dir, prefix + 'qapi-event.h')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+    genc.write(output_dir, prefix + 'qapi-event.c')
+    genh.write(output_dir, prefix + 'qapi-event.h')
diff --git a/scripts/qapi-introspect.py b/scripts/qapi/introspect.py
similarity index 90%
rename from scripts/qapi-introspect.py
rename to scripts/qapi/introspect.py
index b098b95053..1e4f065164 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi/introspect.py
@@ -10,7 +10,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
 See the COPYING file in the top-level directory.
 """
 
-from qapi import *
+from qapi.common import *
 
 
 # Caveman's json.dumps() replacement (we're stuck at Python 2.4)
@@ -168,22 +168,8 @@ const char %(c_name)s[] = %(c_string)s;
         self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
 
 
-def main(argv):
-    # Debugging aid: unmask QAPI schema's type names
-    # We normally mask them, because they're not QMP wire ABI
-    opt_unmask = False
-
-    (input_file, output_dir, do_c, do_h, prefix, opts) = \
-        parse_command_line('u', ['unmask-non-abi-names'])
-
-    for o, a in opts:
-        if o in ('-u', '--unmask-non-abi-names'):
-            opt_unmask = True
-
-    blurb = '''
- * QAPI/QMP schema introspection
-'''
-
+def gen_introspect(schema, output_dir, prefix, opt_unmask):
+    blurb = ' * QAPI/QMP schema introspection'
     genc = QAPIGenC(blurb, __doc__)
     genh = QAPIGenH(blurb, __doc__)
 
@@ -194,17 +180,9 @@ def main(argv):
 ''',
                    prefix=prefix))
 
-    schema = QAPISchema(input_file)
     vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-
-    if do_c:
-        genc.write(output_dir, prefix + 'qmp-introspect.c')
-    if do_h:
-        genh.write(output_dir, prefix + 'qmp-introspect.h')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+    genc.write(output_dir, prefix + 'qmp-introspect.c')
+    genh.write(output_dir, prefix + 'qmp-introspect.h')
diff --git a/scripts/qapi-types.py b/scripts/qapi/types.py
similarity index 90%
rename from scripts/qapi-types.py
rename to scripts/qapi/types.py
index 10955d1c01..aa3c01e750 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi/types.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
 # See the COPYING file in the top-level directory.
 """
 
-from qapi import *
+from qapi.common import *
 
 
 # variants must be emitted before their container; track what has already
@@ -241,24 +241,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self._gen_type_cleanup(name)
 
 
-def main(argv):
-    # If you link code generated from multiple schemata, you want only one
-    # instance of the code for built-in types.  Generate it only when
-    # opt_builtins, enabled by command line option -b.  See also
-    # QAPISchemaGenTypeVisitor.visit_end().
-    opt_builtins = False
-
-    (input_file, output_dir, do_c, do_h, prefix, opts) = \
-        parse_command_line('b', ['builtins'])
-
-    for o, a in opts:
-        if o in ('-b', '--builtins'):
-            opt_builtins = True
-
-    blurb = '''
- * Schema-defined QAPI types
-'''
-
+def gen_types(schema, output_dir, prefix, opt_builtins):
+    blurb = ' * Schema-defined QAPI types'
     genc = QAPIGenC(blurb, __doc__)
     genh = QAPIGenH(blurb, __doc__)
 
@@ -274,17 +258,9 @@ def main(argv):
 #include "qapi/util.h"
 '''))
 
-    schema = QAPISchema(input_file)
     vis = QAPISchemaGenTypeVisitor(opt_builtins)
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-
-    if do_c:
-        genc.write(output_dir, prefix + 'qapi-types.c')
-    if do_h:
-        genh.write(output_dir, prefix + 'qapi-types.h')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+    genc.write(output_dir, prefix + 'qapi-types.c')
+    genh.write(output_dir, prefix + 'qapi-types.h')
diff --git a/scripts/qapi-visit.py b/scripts/qapi/visit.py
similarity index 92%
rename from scripts/qapi-visit.py
rename to scripts/qapi/visit.py
index 6d829c4d1d..f966e7975f 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi/visit.py
@@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
 See the COPYING file in the top-level directory.
 """
 
-from qapi import *
+from qapi.common import *
 
 
 def gen_visit_decl(name, scalar=False):
@@ -324,24 +324,8 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         self.defn += gen_visit_alternate(name, variants)
 
 
-def main(argv):
-    # If you link code generated from multiple schemata, you want only one
-    # instance of the code for built-in types.  Generate it only when
-    # opt_builtins, enabled by command line option -b.  See also
-    # QAPISchemaGenVisitVisitor.visit_end().
-    opt_builtins = False
-
-    (input_file, output_dir, do_c, do_h, prefix, opts) = \
-        parse_command_line('b', ['builtins'])
-
-    for o, a in opts:
-        if o in ('-b', '--builtins'):
-            opt_builtins = True
-
-    blurb = '''
- * Schema-defined QAPI visitors
-'''
-
+def gen_visit(schema, output_dir, prefix, opt_builtins):
+    blurb = ' * Schema-defined QAPI visitors'
     genc = QAPIGenC(blurb, __doc__)
     genh = QAPIGenH(blurb, __doc__)
 
@@ -361,17 +345,9 @@ def main(argv):
 ''',
                    prefix=prefix))
 
-    schema = QAPISchema(input_file)
     vis = QAPISchemaGenVisitVisitor(opt_builtins)
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-
-    if do_c:
-        genc.write(output_dir, prefix + 'qapi-visit.c')
-    if do_h:
-        genh.write(output_dir, prefix + 'qapi-visit.h')
-
-
-if __name__ == '__main__':
-    main(sys.argv)
+    genc.write(output_dir, prefix + 'qapi-visit.c')
+    genh.write(output_dir, prefix + 'qapi-visit.h')
diff --git a/tests/Makefile.include b/tests/Makefile.include
index f41da235ae..b406531b34 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -23,7 +23,16 @@ check-help:
 ifneq ($(wildcard config-host.mak),)
 export SRC_PATH
 
-qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
+# TODO don't duplicate $(SRC_PATH)/Makefile's qapi-py here
+qapi-py = $(SRC_PATH)/scripts/qapi/commands.py \
+$(SRC_PATH)/scripts/qapi/events.py \
+$(SRC_PATH)/scripts/qapi/introspect.py \
+$(SRC_PATH)/scripts/qapi/types.py \
+$(SRC_PATH)/scripts/qapi/visit.py \
+$(SRC_PATH)/scripts/qapi/common.py \
+$(SRC_PATH)/scripts/qapi/doc.py \
+$(SRC_PATH)/scripts/ordereddict.py \
+$(SRC_PATH)/scripts/qapi-gen.py
 
 # Get the list of all supported sysemu targets
 SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
@@ -645,34 +654,24 @@ tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
 	$(test-block-obj-y)
 
-tests/test-qapi-types.c tests/test-qapi-types.h :\
-$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
-		$(gen-out-type) -o tests -p "test-" $<, \
-		"GEN","$@")
-tests/test-qapi-visit.c tests/test-qapi-visit.h :\
-$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
-		$(gen-out-type) -o tests -p "test-" $<, \
-		"GEN","$@")
-tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
-$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
-		$(gen-out-type) -o tests -p "test-" $<, \
-		"GEN","$@")
-tests/test-qapi-event.c tests/test-qapi-event.h :\
-$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
-		$(gen-out-type) -o tests -p "test-" $<, \
-		"GEN","$@")
-tests/test-qmp-introspect.c tests/test-qmp-introspect.h :\
-$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
-		$(gen-out-type) -o tests -p "test-" $<, \
-		"GEN","$@")
+tests/test-qapi-types.c tests/test-qapi-types.h \
+tests/test-qapi-visit.c tests/test-qapi-visit.h \
+tests/test-qmp-commands.h tests/test-qmp-marshal.c \
+tests/test-qapi-event.c tests/test-qapi-event.h \
+tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
+tests/test-qapi-gen-timestamp ;
+tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
+		-o tests -p "test-" $<, \
+		"GEN","$(@:%-timestamp=%)")
+	@>$@
 
-tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
+tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(qapi-py)
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
+		-o tests/qapi-schema -p "doc-good-" $<, \
+		"GEN","$@")
+	@mv tests/qapi-schema/doc-good-qapi-doc.texi $@
+	@rm -f tests/qapi-schema/doc-good-qapi-*.[ch] tests/qapi-schema/doc-good-qmp-*.[ch]
 
 tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
 tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
@@ -941,6 +940,7 @@ check-clean:
 	$(MAKE) -C tests/tcg clean
 	rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
 	rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))
+	rm -f tests/test-qapi-gen-timestamp
 
 clean: check-clean
 
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index ac43d3458e..bb1b6dd297 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -11,10 +11,8 @@
 #
 
 from __future__ import print_function
-from qapi import *
-from pprint import pprint
-import os
 import sys
+from qapi.common import QAPISchema, QAPISchemaVisitor
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (7 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:44   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
                   ` (22 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

argparse is nicer to use than getopt, and gives us --help almost for
free.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi-gen.py    | 48 ++++++++++++++++++++++++++++++------------------
 scripts/qapi/common.py | 43 -------------------------------------------
 2 files changed, 30 insertions(+), 61 deletions(-)

diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
index 2100ca1145..e5be484e3e 100755
--- a/scripts/qapi-gen.py
+++ b/scripts/qapi-gen.py
@@ -4,8 +4,11 @@
 # This work is licensed under the terms of the GNU GPL, version 2 or later.
 # See the COPYING file in the top-level directory.
 
+from __future__ import print_function
+import argparse
+import re
 import sys
-from qapi.common import parse_command_line, QAPISchema
+from qapi.common import QAPISchema
 from qapi.types import gen_types
 from qapi.visit import gen_visit
 from qapi.commands import gen_commands
@@ -15,26 +18,35 @@ from qapi.doc import gen_doc
 
 
 def main(argv):
-    (input_file, output_dir, prefix, opts) = \
-        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
+    parser = argparse.ArgumentParser(
+        description='Generate code from a QAPI schema')
+    parser.add_argument('-b', '--builtins', action='store_true',
+                        help="generate code for built-in types")
+    parser.add_argument('-o', '--output_dir', action='store', default='',
+                        help="write output to directory OUTPUT_DIR")
+    parser.add_argument('-p', '--prefix', action='store', default='',
+                        help="prefix for symbols")
+    parser.add_argument('-u', '--unmask-non-abi-names', action='store_true',
+                        dest='unmask',
+                        help="expose non-ABI names in introspection")
+    parser.add_argument('schema', action='store')
+    args = parser.parse_args()
 
-    opt_builtins = False
-    opt_unmask = False
+    match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', args.prefix)
+    if match.end() != len(args.prefix):
+        print("%s: 'funny character '%s' in argument of --prefix"
+              % (sys.argv[0], args.prefix[match.end()]),
+              file=sys.stderr)
+        sys.exit(1)
 
-    for o, a in opts:
-        if o in ('-b', '--builtins'):
-            opt_builtins = True
-        if o in ('-u', '--unmask-non-abi-names'):
-            opt_unmask = True
+    schema = QAPISchema(args.schema)
 
-    schema = QAPISchema(input_file)
-
-    gen_types(schema, output_dir, prefix, opt_builtins)
-    gen_visit(schema, output_dir, prefix, opt_builtins)
-    gen_commands(schema, output_dir, prefix)
-    gen_events(schema, output_dir, prefix)
-    gen_introspect(schema, output_dir, prefix, opt_unmask)
-    gen_doc(schema, output_dir, prefix)
+    gen_types(schema, args.output_dir, args.prefix, args.builtins)
+    gen_visit(schema, args.output_dir, args.prefix, args.builtins)
+    gen_commands(schema, args.output_dir, args.prefix)
+    gen_events(schema, args.output_dir, args.prefix)
+    gen_introspect(schema, args.output_dir, args.prefix, args.unmask)
+    gen_doc(schema, args.output_dir, args.prefix)
 
 
 if __name__ == '__main__':
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 868ec25deb..8290795dc1 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -13,7 +13,6 @@
 
 from __future__ import print_function
 import errno
-import getopt
 import os
 import re
 import string
@@ -1924,48 +1923,6 @@ def build_params(arg_type, boxed, extra):
 
 
 #
-# Common command line parsing
-#
-
-
-def parse_command_line(extra_options='', extra_long_options=[]):
-
-    try:
-        opts, args = getopt.gnu_getopt(sys.argv[1:],
-                                       'p:o:' + extra_options,
-                                       ['prefix=', 'output-dir=']
-                                       + extra_long_options)
-    except getopt.GetoptError as err:
-        print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
-        sys.exit(1)
-
-    output_dir = ''
-    prefix = ''
-    extra_opts = []
-
-    for oa in opts:
-        o, a = oa
-        if o in ('-p', '--prefix'):
-            match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
-            if match.end() != len(a):
-                print("%s: 'funny character '%s' in argument of --prefix" \
-                      % (sys.argv[0], a[match.end()]), file=sys.stderr)
-                sys.exit(1)
-            prefix = a
-        elif o in ('-o', '--output-dir'):
-            output_dir = a + '/'
-        else:
-            extra_opts.append(oa)
-
-    if len(args) != 1:
-        print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
-        sys.exit(1)
-    fname = args[0]
-
-    return (fname, output_dir, prefix, extra_opts)
-
-
-#
 # Accumulate and write output
 #
 
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (8 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:48   ` Eric Blake
  2018-02-18 22:43   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages Markus Armbruster
                   ` (21 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

A massive number of objects depends on QAPI-generated headers.  In my
"build everything" tree, it's roughly 4800 out of 5100.  This is
particularly annoying when only some of the generated files change,
say for a doc fix.

Improve qapi-gen.py to touch its output files only if they actually
change.  Rebuild time for a QAPI doc fix drops from many minutes to a
few seconds.  Rebuilds get faster for certain code changes, too.  For
instance, adding a simple QMP event now recompiles less than 200
instead of 4800 objects.  But adding a QAPI type is as bad as ever;
we've clearly got more work to do.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 scripts/qapi/common.py | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 8290795dc1..2e58573a39 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1951,9 +1951,16 @@ class QAPIGen(object):
             except os.error as e:
                 if e.errno != errno.EEXIST:
                     raise
-        f = open(os.path.join(output_dir, fname), 'w')
-        f.write(self._top(fname) + self._preamble + self._body
+        fd = os.open(os.path.join(output_dir, fname),
+                     os.O_RDWR | os.O_CREAT, 0666)
+        f = os.fdopen(fd, 'r+')
+        text = (self._top(fname) + self._preamble + self._body
                 + self._bottom(fname))
+        oldtext = f.read(len(text) + 1)
+        if text != oldtext:
+            f.seek(0)
+            f.truncate(0)
+            f.write(text)
         f.close()
 
 
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (9 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-18 23:11   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs Markus Armbruster
                   ` (20 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Error messages print absolute file names of included files even if the
user gave a relative one on the command line:

    $ PYTHONPATH=scripts python -B tests/qapi-schema/test-qapi.py tests/qapi-schema/include-cycle.json
    In file included from tests/qapi-schema/include-cycle.json:1:
    In file included from /work/armbru/qemu/tests/qapi-schema/include-cycle-b.json:1:
    /work/armbru/qemu/tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json

Improve this to

    In file included from tests/qapi-schema/include-cycle.json:1:
    In file included from tests/qapi-schema/include-cycle-b.json:1:
    tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json

The error message when an include file can't be opened prints the
include directive's file name, which is relative to the including
file.  Change this to print the file name relative to the working
directory.  Visible in tests/qapi-schema/include-no-file.err.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                | 12 ++++++------
 tests/qapi-schema/include-no-file.err |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 2e58573a39..3e92b38ade 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -259,9 +259,8 @@ class QAPIDoc(object):
 class QAPISchemaParser(object):
 
     def __init__(self, fp, previously_included=[], incl_info=None):
-        abs_fname = os.path.abspath(fp.name)
         self.fname = fp.name
-        previously_included.append(abs_fname)
+        previously_included.append(os.path.abspath(fp.name))
         self.incl_info = incl_info
         self.src = fp.read()
         if self.src == '' or self.src[-1] != '\n':
@@ -292,7 +291,7 @@ class QAPISchemaParser(object):
                 if not isinstance(include, str):
                     raise QAPISemError(info,
                                        "Value of 'include' must be a string")
-                self._include(include, info, os.path.dirname(abs_fname),
+                self._include(include, info, os.path.dirname(self.fname),
                               previously_included)
             elif "pragma" in expr:
                 self.reject_expr_doc(cur_doc)
@@ -325,7 +324,8 @@ class QAPISchemaParser(object):
                 % doc.symbol)
 
     def _include(self, include, info, base_dir, previously_included):
-        incl_abs_fname = os.path.join(base_dir, include)
+        incl_fname = os.path.join(base_dir, include)
+        incl_abs_fname = os.path.abspath(incl_fname)
         # catch inclusion cycle
         inf = info
         while inf:
@@ -337,9 +337,9 @@ class QAPISchemaParser(object):
         if incl_abs_fname in previously_included:
             return
         try:
-            fobj = open(incl_abs_fname, 'r')
+            fobj = open(incl_fname, 'r')
         except IOError as e:
-            raise QAPISemError(info, '%s: %s' % (e.strerror, include))
+            raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
         exprs_include = QAPISchemaParser(fobj, previously_included, info)
         self.exprs.extend(exprs_include.exprs)
         self.docs.extend(exprs_include.docs)
diff --git a/tests/qapi-schema/include-no-file.err b/tests/qapi-schema/include-no-file.err
index d5b9b22d85..e42bcf4bc1 100644
--- a/tests/qapi-schema/include-no-file.err
+++ b/tests/qapi-schema/include-no-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-no-file.json:1: No such file or directory: include-no-file-sub.json
+tests/qapi-schema/include-no-file.json:1: No such file or directory: tests/qapi-schema/include-no-file-sub.json
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (10 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-18 23:13   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
                   ` (19 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

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

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 3e92b38ade..d72c339ad5 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1461,13 +1461,13 @@ class QAPISchema(object):
     def __init__(self, fname):
         try:
             parser = QAPISchemaParser(open(fname, 'r'))
-            self.exprs = check_exprs(parser.exprs)
+            exprs = check_exprs(parser.exprs)
             self.docs = parser.docs
             self._entity_dict = {}
             self._predefining = True
             self._def_predefineds()
             self._predefining = False
-            self._def_exprs()
+            self._def_exprs(exprs)
             self.check()
         except QAPIError as err:
             print(err, file=sys.stderr)
@@ -1652,8 +1652,8 @@ class QAPISchema(object):
                 name, info, doc, 'arg', self._make_members(data, info))
         self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed))
 
-    def _def_exprs(self):
-        for expr_elem in self.exprs:
+    def _def_exprs(self, exprs):
+        for expr_elem in exprs:
             expr = expr_elem['expr']
             info = expr_elem['info']
             doc = expr_elem.get('doc')
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (11 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:52   ` Eric Blake
  2018-02-18 23:17   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
                   ` (18 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-gen.py            |  8 ++++++--
 scripts/qapi/common.py         | 23 +++++++++--------------
 tests/qapi-schema/test-qapi.py | 10 ++++++++--
 3 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
index e5be484e3e..fea7d4589b 100755
--- a/scripts/qapi-gen.py
+++ b/scripts/qapi-gen.py
@@ -8,7 +8,7 @@ from __future__ import print_function
 import argparse
 import re
 import sys
-from qapi.common import QAPISchema
+from qapi.common import QAPIError, QAPISchema
 from qapi.types import gen_types
 from qapi.visit import gen_visit
 from qapi.commands import gen_commands
@@ -39,7 +39,11 @@ def main(argv):
               file=sys.stderr)
         sys.exit(1)
 
-    schema = QAPISchema(args.schema)
+    try:
+        schema = QAPISchema(args.schema)
+    except QAPIError as err:
+        print(err, file=sys.stderr)
+        exit(1)
 
     gen_types(schema, args.output_dir, args.prefix, args.builtins)
     gen_visit(schema, args.output_dir, args.prefix, args.builtins)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index d72c339ad5..dce289ae21 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -16,7 +16,6 @@ import errno
 import os
 import re
 import string
-import sys
 try:
     from collections import OrderedDict
 except:
@@ -1459,19 +1458,15 @@ class QAPISchemaEvent(QAPISchemaEntity):
 
 class QAPISchema(object):
     def __init__(self, fname):
-        try:
-            parser = QAPISchemaParser(open(fname, 'r'))
-            exprs = check_exprs(parser.exprs)
-            self.docs = parser.docs
-            self._entity_dict = {}
-            self._predefining = True
-            self._def_predefineds()
-            self._predefining = False
-            self._def_exprs(exprs)
-            self.check()
-        except QAPIError as err:
-            print(err, file=sys.stderr)
-            exit(1)
+        parser = QAPISchemaParser(open(fname, 'r'))
+        exprs = check_exprs(parser.exprs)
+        self.docs = parser.docs
+        self._entity_dict = {}
+        self._predefining = True
+        self._def_predefineds()
+        self._predefining = False
+        self._def_exprs(exprs)
+        self.check()
 
     def _def_entity(self, ent):
         # Only the predefined types are allowed to not have info
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index bb1b6dd297..4da14b43af 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -12,7 +12,7 @@
 
 from __future__ import print_function
 import sys
-from qapi.common import QAPISchema, QAPISchemaVisitor
+from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
@@ -52,7 +52,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             for v in variants.variants:
                 print('    case %s: %s' % (v.name, v.type.name))
 
-schema = QAPISchema(sys.argv[1])
+
+try:
+    schema = QAPISchema(sys.argv[1])
+except QAPIError as err:
+    print(err, file=sys.stderr)
+    exit(1)
+
 schema.visit(QAPISchemaTestVisitor())
 
 for doc in schema.docs:
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (12 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 19:56   ` Eric Blake
  2018-02-18 23:32   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
                   ` (17 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

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

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index dce289ae21..cc5a5941dd 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -290,8 +290,12 @@ class QAPISchemaParser(object):
                 if not isinstance(include, str):
                     raise QAPISemError(info,
                                        "Value of 'include' must be a string")
-                self._include(include, info, os.path.dirname(self.fname),
-                              previously_included)
+                exprs_include = self._include(include, info,
+                                              os.path.dirname(self.fname),
+                                              previously_included)
+                if exprs_include:
+                    self.exprs.extend(exprs_include.exprs)
+                    self.docs.extend(exprs_include.docs)
             elif "pragma" in expr:
                 self.reject_expr_doc(cur_doc)
                 if len(expr) != 1:
@@ -334,14 +338,13 @@ class QAPISchemaParser(object):
 
         # skip multiple include of the same file
         if incl_abs_fname in previously_included:
-            return
+            return None
+
         try:
             fobj = open(incl_fname, 'r')
         except IOError as e:
             raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
-        exprs_include = QAPISchemaParser(fobj, previously_included, info)
-        self.exprs.extend(exprs_include.exprs)
-        self.docs.extend(exprs_include.docs)
+        return QAPISchemaParser(fobj, previously_included, info)
 
     def _pragma(self, name, value, info):
         global doc_required, returns_whitelist, name_case_whitelist
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (13 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 20:03   ` Eric Blake
  2018-02-18 23:57   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
                   ` (16 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The parse tree is a list of expressions.  Except include expressions
currently get replaced by the included file's parse tree.

Instead of throwing away the include expression, keep it with the file
name expanded so you don't have to track the including file's
directory to make sense of it.

A future commit will put this include expression to use.

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

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index cc5a5941dd..6d49709784 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -290,8 +290,11 @@ class QAPISchemaParser(object):
                 if not isinstance(include, str):
                     raise QAPISemError(info,
                                        "Value of 'include' must be a string")
-                exprs_include = self._include(include, info,
-                                              os.path.dirname(self.fname),
+                incl_fname = os.path.join(os.path.dirname(self.fname),
+                                          include)
+                self.exprs.append({'expr': {'include': incl_fname},
+                                   'info': info})
+                exprs_include = self._include(include, info, incl_fname,
                                               previously_included)
                 if exprs_include:
                     self.exprs.extend(exprs_include.exprs)
@@ -326,8 +329,7 @@ class QAPISchemaParser(object):
                 "Documentation for '%s' is not followed by the definition"
                 % doc.symbol)
 
-    def _include(self, include, info, base_dir, previously_included):
-        incl_fname = os.path.join(base_dir, include)
+    def _include(self, include, info, incl_fname, previously_included):
         incl_abs_fname = os.path.abspath(incl_fname)
         # catch inclusion cycle
         inf = info
@@ -893,6 +895,9 @@ def check_exprs(exprs):
         info = expr_elem['info']
         doc = expr_elem.get('doc')
 
+        if 'include' in expr:
+            continue
+
         if not doc and doc_required:
             raise QAPISemError(info,
                                "Expression missing documentation comment")
@@ -931,6 +936,9 @@ def check_exprs(exprs):
 
     # Try again for hidden UnionKind enum
     for expr_elem in exprs:
+        if 'include' in expr:
+            continue
+
         expr = expr_elem['expr']
         if 'union' in expr and not discriminator_find_enum_define(expr):
             name = '%sKind' % expr['union']
@@ -943,6 +951,9 @@ def check_exprs(exprs):
 
     # Validate that exprs make sense
     for expr_elem in exprs:
+        if 'include' in expr:
+            continue
+
         expr = expr_elem['expr']
         info = expr_elem['info']
         doc = expr_elem.get('doc')
@@ -1667,6 +1678,8 @@ class QAPISchema(object):
                 self._def_command(expr, info, doc)
             elif 'event' in expr:
                 self._def_event(expr, info, doc)
+            elif 'include' in expr:
+                pass
             else:
                 assert False
 
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (14 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 20:06   ` Eric Blake
  2018-02-19  0:01   ` Michael Roth
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation Markus Armbruster
                   ` (15 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The generators' conversion to visitors (merge commit 9e72681d16)
changed the processing order of entities from source order to
alphabetical order.  The next commit needs source order, so change it
back.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                   |   6 +-
 tests/qapi-schema/comments.out           |   2 +-
 tests/qapi-schema/doc-bad-section.out    |   4 +-
 tests/qapi-schema/doc-good.out           |  32 ++--
 tests/qapi-schema/empty.out              |   2 +-
 tests/qapi-schema/event-case.out         |   2 +-
 tests/qapi-schema/ident-with-escape.out  |   6 +-
 tests/qapi-schema/include-relpath.out    |   2 +-
 tests/qapi-schema/include-repetition.out |   2 +-
 tests/qapi-schema/include-simple.out     |   2 +-
 tests/qapi-schema/indented-expr.out      |   2 +-
 tests/qapi-schema/qapi-schema-test.out   | 320 +++++++++++++++----------------
 12 files changed, 192 insertions(+), 190 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 6d49709784..b531ab519f 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1475,6 +1475,7 @@ class QAPISchema(object):
         parser = QAPISchemaParser(open(fname, 'r'))
         exprs = check_exprs(parser.exprs)
         self.docs = parser.docs
+        self._entity_list = []
         self._entity_dict = {}
         self._predefining = True
         self._def_predefineds()
@@ -1486,6 +1487,7 @@ class QAPISchema(object):
         # Only the predefined types are allowed to not have info
         assert ent.info or self._predefining
         assert ent.name not in self._entity_dict
+        self._entity_list.append(ent)
         self._entity_dict[ent.name] = ent
 
     def lookup_entity(self, name, typ=None):
@@ -1684,12 +1686,12 @@ class QAPISchema(object):
                 assert False
 
     def check(self):
-        for (name, ent) in sorted(self._entity_dict.items()):
+        for ent in self._entity_list:
             ent.check(self)
 
     def visit(self, visitor):
         visitor.visit_begin(self)
-        for (name, entity) in sorted(self._entity_dict.items()):
+        for entity in self._entity_list:
             if visitor.visit_needed(entity):
                 entity.visit(visitor)
         visitor.visit_end()
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
index 17e652535c..0261ddf202 100644
--- a/tests/qapi-schema/comments.out
+++ b/tests/qapi-schema/comments.out
@@ -1,4 +1,4 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
-object q_empty
diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out
index 089bde1381..23bf8c71ab 100644
--- a/tests/qapi-schema/doc-bad-section.out
+++ b/tests/qapi-schema/doc-bad-section.out
@@ -1,7 +1,7 @@
-enum Enum ['one', 'two']
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
-object q_empty
+enum Enum ['one', 'two']
 doc symbol=Enum
     body=
 == Produces *invalid* texinfo
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 1d2c250527..0c07301f07 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -1,35 +1,35 @@
+object q_empty
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+    prefix QTYPE
+enum Enum ['one', 'two']
 object Base
     member base1: Enum optional=False
-enum Enum ['one', 'two']
+object Variant1
+    member var1: str optional=False
+object Variant2
 object Object
     base Base
     tag base1
     case one: Variant1
     case two: Variant2
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
-    prefix QTYPE
+object q_obj_Variant1-wrapper
+    member data: Variant1 optional=False
+object q_obj_Variant2-wrapper
+    member data: Variant2 optional=False
+enum SugaredUnionKind ['one', 'two']
 object SugaredUnion
     member type: SugaredUnionKind optional=False
     tag type
     case one: q_obj_Variant1-wrapper
     case two: q_obj_Variant2-wrapper
-enum SugaredUnionKind ['one', 'two']
-object Variant1
-    member var1: str optional=False
-object Variant2
-command cmd q_obj_cmd-arg -> Object
-   gen=True success_response=True boxed=False
-command cmd-boxed Object -> None
-   gen=True success_response=True boxed=True
-object q_empty
-object q_obj_Variant1-wrapper
-    member data: Variant1 optional=False
-object q_obj_Variant2-wrapper
-    member data: Variant2 optional=False
 object q_obj_cmd-arg
     member arg1: int optional=False
     member arg2: str optional=True
     member arg3: bool optional=False
+command cmd q_obj_cmd-arg -> Object
+   gen=True success_response=True boxed=False
+command cmd-boxed Object -> None
+   gen=True success_response=True boxed=True
 doc freeform
     body=
 = Section
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
index 40b886ddae..0ec234eec4 100644
--- a/tests/qapi-schema/empty.out
+++ b/tests/qapi-schema/empty.out
@@ -1,3 +1,3 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
-object q_empty
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 313c0fe7be..110571b793 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,5 +1,5 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 event oops None
    boxed=False
-object q_empty
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index b5637cb2e0..8336aa7629 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,7 +1,7 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
-command fooA q_obj_fooA-arg -> None
-   gen=True success_response=True boxed=False
-object q_empty
 object q_obj_fooA-arg
     member bar1: str optional=False
+command fooA q_obj_fooA-arg -> None
+   gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
index 17e652535c..0261ddf202 100644
--- a/tests/qapi-schema/include-relpath.out
+++ b/tests/qapi-schema/include-relpath.out
@@ -1,4 +1,4 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
-object q_empty
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
index 17e652535c..0261ddf202 100644
--- a/tests/qapi-schema/include-repetition.out
+++ b/tests/qapi-schema/include-repetition.out
@@ -1,4 +1,4 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
-object q_empty
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
index 17e652535c..0261ddf202 100644
--- a/tests/qapi-schema/include-simple.out
+++ b/tests/qapi-schema/include-simple.out
@@ -1,4 +1,4 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
-object q_empty
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index 586795f44d..34de8be426 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,7 +1,7 @@
+object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
 command eins None -> None
    gen=True success_response=True boxed=False
-object q_empty
 command zwei None -> None
    gen=True success_response=True boxed=False
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 3b1e9082d3..50706b0136 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,87 +1,129 @@
-alternate AltEnumBool
-    tag type
-    case e: EnumOne
-    case b: bool
-alternate AltEnumInt
-    tag type
-    case e: EnumOne
-    case i: int
-alternate AltEnumNum
-    tag type
-    case e: EnumOne
-    case n: number
-alternate AltNumEnum
-    tag type
-    case n: number
-    case e: EnumOne
-alternate AltStrObj
-    tag type
-    case s: str
-    case o: TestStruct
-event EVENT_A None
-   boxed=False
-event EVENT_B None
-   boxed=False
-event EVENT_C q_obj_EVENT_C-arg
-   boxed=False
-event EVENT_D q_obj_EVENT_D-arg
-   boxed=False
-event EVENT_E UserDefZero
-   boxed=True
-event EVENT_F UserDefAlternate
-   boxed=True
+object q_empty
+enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
+    prefix QTYPE
+object TestStruct
+    member integer: int optional=False
+    member boolean: bool optional=False
+    member string: str optional=False
+object NestedEnumsOne
+    member enum1: EnumOne optional=False
+    member enum2: EnumOne optional=True
+    member enum3: EnumOne optional=False
+    member enum4: EnumOne optional=True
+enum MyEnum []
 object Empty1
 object Empty2
     base Empty1
+command user_def_cmd0 Empty2 -> Empty2
+   gen=True success_response=True boxed=False
+enum QEnumTwo ['value1', 'value2']
+    prefix QENUM_TWO
+object UserDefOne
+    base UserDefZero
+    member string: str optional=False
+    member enum1: EnumOne optional=True
 enum EnumOne ['value1', 'value2', 'value3']
-object EventStructOne
-    member struct1: UserDefOne optional=False
+object UserDefZero
+    member integer: int optional=False
+object UserDefTwoDictDict
+    member userdef: UserDefOne optional=False
     member string: str optional=False
-    member enum2: EnumOne optional=True
+object UserDefTwoDict
+    member string1: str optional=False
+    member dict2: UserDefTwoDictDict optional=False
+    member dict3: UserDefTwoDictDict optional=True
+object UserDefTwo
+    member string0: str optional=False
+    member dict1: UserDefTwoDict optional=False
 object ForceArrays
     member unused1: UserDefOneList optional=False
     member unused2: UserDefTwoList optional=False
     member unused3: TestStructList optional=False
-enum MyEnum []
-object NestedEnumsOne
-    member enum1: EnumOne optional=False
-    member enum2: EnumOne optional=True
-    member enum3: EnumOne optional=False
-    member enum4: EnumOne optional=True
-enum QEnumTwo ['value1', 'value2']
-    prefix QENUM_TWO
-enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
-    prefix QTYPE
-object TestStruct
-    member integer: int optional=False
-    member boolean: bool optional=False
-    member string: str optional=False
 object UserDefA
     member boolean: bool optional=False
     member a_b: int optional=True
-alternate UserDefAlternate
-    tag type
-    case udfu: UserDefFlatUnion
-    case e: EnumOne
-    case i: int
-    case n: null
 object UserDefB
     member intb: int optional=False
     member a-b: bool optional=True
-object UserDefC
-    member string1: str optional=False
-    member string2: str optional=False
 object UserDefFlatUnion
     base UserDefUnionBase
     tag enum1
     case value1: UserDefA
     case value2: UserDefB
     case value3: UserDefB
+object UserDefUnionBase
+    base UserDefZero
+    member string: str optional=False
+    member enum1: EnumOne optional=False
+object q_obj_UserDefFlatUnion2-base
+    member integer: int optional=True
+    member string: str optional=False
+    member enum1: QEnumTwo optional=False
 object UserDefFlatUnion2
     base q_obj_UserDefFlatUnion2-base
     tag enum1
     case value1: UserDefC
     case value2: UserDefB
+object WrapAlternate
+    member alt: UserDefAlternate optional=False
+alternate UserDefAlternate
+    tag type
+    case udfu: UserDefFlatUnion
+    case e: EnumOne
+    case i: int
+    case n: null
+object UserDefC
+    member string1: str optional=False
+    member string2: str optional=False
+alternate AltEnumBool
+    tag type
+    case e: EnumOne
+    case b: bool
+alternate AltEnumNum
+    tag type
+    case e: EnumOne
+    case n: number
+alternate AltNumEnum
+    tag type
+    case n: number
+    case e: EnumOne
+alternate AltEnumInt
+    tag type
+    case e: EnumOne
+    case i: int
+alternate AltStrObj
+    tag type
+    case s: str
+    case o: TestStruct
+object q_obj_intList-wrapper
+    member data: intList optional=False
+object q_obj_int8List-wrapper
+    member data: int8List optional=False
+object q_obj_int16List-wrapper
+    member data: int16List optional=False
+object q_obj_int32List-wrapper
+    member data: int32List optional=False
+object q_obj_int64List-wrapper
+    member data: int64List optional=False
+object q_obj_uint8List-wrapper
+    member data: uint8List optional=False
+object q_obj_uint16List-wrapper
+    member data: uint16List optional=False
+object q_obj_uint32List-wrapper
+    member data: uint32List optional=False
+object q_obj_uint64List-wrapper
+    member data: uint64List optional=False
+object q_obj_numberList-wrapper
+    member data: numberList optional=False
+object q_obj_boolList-wrapper
+    member data: boolList optional=False
+object q_obj_strList-wrapper
+    member data: strList optional=False
+object q_obj_sizeList-wrapper
+    member data: sizeList optional=False
+object q_obj_anyList-wrapper
+    member data: anyList optional=False
+enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
 object UserDefNativeListUnion
     member type: UserDefNativeListUnionKind optional=False
     tag type
@@ -99,133 +141,91 @@ object UserDefNativeListUnion
     case string: q_obj_strList-wrapper
     case sizes: q_obj_sizeList-wrapper
     case any: q_obj_anyList-wrapper
-enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
-object UserDefOne
-    base UserDefZero
-    member string: str optional=False
-    member enum1: EnumOne optional=True
+command user_def_cmd None -> None
+   gen=True success_response=True boxed=False
+object q_obj_user_def_cmd1-arg
+    member ud1a: UserDefOne optional=False
+command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
+   gen=True success_response=True boxed=False
+object q_obj_user_def_cmd2-arg
+    member ud1a: UserDefOne optional=False
+    member ud1b: UserDefOne optional=True
+command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
+   gen=True success_response=True boxed=False
+object q_obj_guest-get-time-arg
+    member a: int optional=False
+    member b: int optional=True
+command guest-get-time q_obj_guest-get-time-arg -> int
+   gen=True success_response=True boxed=False
+object q_obj_guest-sync-arg
+    member arg: any optional=False
+command guest-sync q_obj_guest-sync-arg -> any
+   gen=True success_response=True boxed=False
+command boxed-struct UserDefZero -> None
+   gen=True success_response=True boxed=True
+command boxed-union UserDefNativeListUnion -> None
+   gen=True success_response=True boxed=True
 object UserDefOptions
     member i64: intList optional=True
     member u64: uint64List optional=True
     member u16: uint16List optional=True
     member i64x: int optional=True
     member u64x: uint64 optional=True
-object UserDefTwo
-    member string0: str optional=False
-    member dict1: UserDefTwoDict optional=False
-object UserDefTwoDict
-    member string1: str optional=False
-    member dict2: UserDefTwoDictDict optional=False
-    member dict3: UserDefTwoDictDict optional=True
-object UserDefTwoDictDict
-    member userdef: UserDefOne optional=False
+object EventStructOne
+    member struct1: UserDefOne optional=False
     member string: str optional=False
-object UserDefUnionBase
-    base UserDefZero
-    member string: str optional=False
-    member enum1: EnumOne optional=False
-object UserDefZero
-    member integer: int optional=False
-object WrapAlternate
-    member alt: UserDefAlternate optional=False
-event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+    member enum2: EnumOne optional=True
+event EVENT_A None
+   boxed=False
+event EVENT_B None
+   boxed=False
+object q_obj_EVENT_C-arg
+    member a: int optional=True
+    member b: UserDefOne optional=True
+    member c: str optional=False
+event EVENT_C q_obj_EVENT_C-arg
+   boxed=False
+object q_obj_EVENT_D-arg
+    member a: EventStructOne optional=False
+    member b: str optional=False
+    member c: str optional=True
+    member enum3: EnumOne optional=True
+event EVENT_D q_obj_EVENT_D-arg
    boxed=False
-alternate __org.qemu_x-Alt
-    tag type
-    case __org.qemu_x-branch: str
-    case b: __org.qemu_x-Base
+event EVENT_E UserDefZero
+   boxed=True
+event EVENT_F UserDefAlternate
+   boxed=True
+enum __org.qemu_x-Enum ['__org.qemu_x-value']
 object __org.qemu_x-Base
     member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
-enum __org.qemu_x-Enum ['__org.qemu_x-value']
 object __org.qemu_x-Struct
     base __org.qemu_x-Base
     member __org.qemu_x-member2: str optional=False
     member wchar-t: int optional=True
-object __org.qemu_x-Struct2
-    member array: __org.qemu_x-Union1List optional=False
+object q_obj_str-wrapper
+    member data: str optional=False
+enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
 object __org.qemu_x-Union1
     member type: __org.qemu_x-Union1Kind optional=False
     tag type
     case __org.qemu_x-branch: q_obj_str-wrapper
-enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
+object __org.qemu_x-Struct2
+    member array: __org.qemu_x-Union1List optional=False
 object __org.qemu_x-Union2
     base __org.qemu_x-Base
     tag __org.qemu_x-member1
     case __org.qemu_x-value: __org.qemu_x-Struct2
-command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
-   gen=True success_response=True boxed=False
-command boxed-struct UserDefZero -> None
-   gen=True success_response=True boxed=True
-command boxed-union UserDefNativeListUnion -> None
-   gen=True success_response=True boxed=True
-command guest-get-time q_obj_guest-get-time-arg -> int
-   gen=True success_response=True boxed=False
-command guest-sync q_obj_guest-sync-arg -> any
-   gen=True success_response=True boxed=False
-object q_empty
-object q_obj_EVENT_C-arg
-    member a: int optional=True
-    member b: UserDefOne optional=True
-    member c: str optional=False
-object q_obj_EVENT_D-arg
-    member a: EventStructOne optional=False
-    member b: str optional=False
-    member c: str optional=True
-    member enum3: EnumOne optional=True
-object q_obj_UserDefFlatUnion2-base
-    member integer: int optional=True
-    member string: str optional=False
-    member enum1: QEnumTwo optional=False
+alternate __org.qemu_x-Alt
+    tag type
+    case __org.qemu_x-branch: str
+    case b: __org.qemu_x-Base
+event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+   boxed=False
 object q_obj___org.qemu_x-command-arg
     member a: __org.qemu_x-EnumList optional=False
     member b: __org.qemu_x-StructList optional=False
     member c: __org.qemu_x-Union2 optional=False
     member d: __org.qemu_x-Alt optional=False
-object q_obj_anyList-wrapper
-    member data: anyList optional=False
-object q_obj_boolList-wrapper
-    member data: boolList optional=False
-object q_obj_guest-get-time-arg
-    member a: int optional=False
-    member b: int optional=True
-object q_obj_guest-sync-arg
-    member arg: any optional=False
-object q_obj_int16List-wrapper
-    member data: int16List optional=False
-object q_obj_int32List-wrapper
-    member data: int32List optional=False
-object q_obj_int64List-wrapper
-    member data: int64List optional=False
-object q_obj_int8List-wrapper
-    member data: int8List optional=False
-object q_obj_intList-wrapper
-    member data: intList optional=False
-object q_obj_numberList-wrapper
-    member data: numberList optional=False
-object q_obj_sizeList-wrapper
-    member data: sizeList optional=False
-object q_obj_str-wrapper
-    member data: str optional=False
-object q_obj_strList-wrapper
-    member data: strList optional=False
-object q_obj_uint16List-wrapper
-    member data: uint16List optional=False
-object q_obj_uint32List-wrapper
-    member data: uint32List optional=False
-object q_obj_uint64List-wrapper
-    member data: uint64List optional=False
-object q_obj_uint8List-wrapper
-    member data: uint8List optional=False
-object q_obj_user_def_cmd1-arg
-    member ud1a: UserDefOne optional=False
-object q_obj_user_def_cmd2-arg
-    member ud1a: UserDefOne optional=False
-    member ud1b: UserDefOne optional=True
-command user_def_cmd None -> None
-   gen=True success_response=True boxed=False
-command user_def_cmd0 Empty2 -> Empty2
-   gen=True success_response=True boxed=False
-command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
-   gen=True success_response=True boxed=False
-command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
+command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
    gen=True success_response=True boxed=False
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (15 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 20:34   ` Eric Blake
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
                   ` (14 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The include directive permits modular QAPI schemata, but the generated
code is monolithic all the same.  To permit generating modular code,
the front end needs to pass more information on inclusions to the back
ends.  The commit before last added the necessary information to the
parse tree.  This commit adds it to the intermediate representation
and its QAPISchemaVisitor.  A later commit will use this to to
generate modular code.

New entity QAPISchemaInclude represents inclusions.  Call new visitor
method visit_include() for it, so visitors can see the sub-modules a
module includes.

Note that unlike other entities, QAPISchemaInclude has no name, and is
therefore not added to entity_dict.

New QAPISchemaEntity attribute @module names the entity's source file.
Call new visitor method visit_module() when it changes during a visit,
so visitors can keep track of the module being visited.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi/common.py                   | 44 ++++++++++++++++++++++++++++----
 tests/qapi-schema/comments.out           |  1 +
 tests/qapi-schema/doc-bad-section.out    |  1 +
 tests/qapi-schema/doc-good.out           |  1 +
 tests/qapi-schema/event-case.out         |  1 +
 tests/qapi-schema/ident-with-escape.out  |  1 +
 tests/qapi-schema/include-relpath.out    |  5 ++++
 tests/qapi-schema/include-repetition.out | 10 ++++++++
 tests/qapi-schema/include-simple.out     |  3 +++
 tests/qapi-schema/indented-expr.out      |  1 +
 tests/qapi-schema/qapi-schema-test.out   |  1 +
 tests/qapi-schema/test-qapi.py           |  7 +++++
 12 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index b531ab519f..29d98ca934 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -985,8 +985,9 @@ def check_exprs(exprs):
 
 class QAPISchemaEntity(object):
     def __init__(self, name, info, doc):
-        assert isinstance(name, str)
+        assert name is None or isinstance(name, str)
         self.name = name
+        self.module = None
         # For explicitly defined entities, info points to the (explicit)
         # definition.  For builtins (and their arrays), info is None.
         # For implicitly defined entities, info points to a place that
@@ -1015,10 +1016,16 @@ class QAPISchemaVisitor(object):
     def visit_end(self):
         pass
 
+    def visit_module(self, fname):
+        pass
+
     def visit_needed(self, entity):
         # Default to visiting everything
         return True
 
+    def visit_include(self, fname, info):
+        pass
+
     def visit_builtin_type(self, name, info, json_type):
         pass
 
@@ -1045,6 +1052,16 @@ class QAPISchemaVisitor(object):
         pass
 
 
+class QAPISchemaInclude(QAPISchemaEntity):
+
+    def __init__(self, fname, info):
+        QAPISchemaEntity.__init__(self, None, info, None)
+        self.fname = fname
+
+    def visit(self, visitor):
+        visitor.visit_include(self.fname, self.info)
+
+
 class QAPISchemaType(QAPISchemaEntity):
     # Return the C type for common use.
     # For the types we commonly box, this is a pointer type.
@@ -1472,6 +1489,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
 
 class QAPISchema(object):
     def __init__(self, fname):
+        self._fname = fname
         parser = QAPISchemaParser(open(fname, 'r'))
         exprs = check_exprs(parser.exprs)
         self.docs = parser.docs
@@ -1479,16 +1497,19 @@ class QAPISchema(object):
         self._entity_dict = {}
         self._predefining = True
         self._def_predefineds()
-        self._predefining = False
         self._def_exprs(exprs)
         self.check()
 
     def _def_entity(self, ent):
         # Only the predefined types are allowed to not have info
         assert ent.info or self._predefining
-        assert ent.name not in self._entity_dict
+        assert ent.name is None or ent.name not in self._entity_dict
         self._entity_list.append(ent)
-        self._entity_dict[ent.name] = ent
+        if ent.name is not None:
+            self._entity_dict[ent.name] = ent
+        if ent.info:
+            ent.module = os.path.relpath(ent.info['file'],
+                                         os.path.dirname(self._fname))
 
     def lookup_entity(self, name, typ=None):
         ent = self._entity_dict.get(name)
@@ -1499,6 +1520,15 @@ class QAPISchema(object):
     def lookup_type(self, name):
         return self.lookup_entity(name, QAPISchemaType)
 
+    def _def_include(self, expr, info, doc):
+        include = expr['include']
+        assert doc is None
+        main_info = info
+        while main_info['parent']:
+            main_info = main_info['parent']
+        fname = os.path.relpath(include, os.path.dirname(main_info['file']))
+        self._def_entity(QAPISchemaInclude(fname, info))
+
     def _def_builtin_type(self, name, json_type, c_type):
         self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
         # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
@@ -1681,7 +1711,7 @@ class QAPISchema(object):
             elif 'event' in expr:
                 self._def_event(expr, info, doc)
             elif 'include' in expr:
-                pass
+                self._def_include(expr, info, doc)
             else:
                 assert False
 
@@ -1691,8 +1721,12 @@ class QAPISchema(object):
 
     def visit(self, visitor):
         visitor.visit_begin(self)
+        module = None
         for entity in self._entity_list:
             if visitor.visit_needed(entity):
+                if entity.module != module:
+                    module = entity.module
+                    visitor.visit_module(module)
                 entity.visit(visitor)
         visitor.visit_end()
 
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
index 0261ddf202..8d2f1ce8a2 100644
--- a/tests/qapi-schema/comments.out
+++ b/tests/qapi-schema/comments.out
@@ -1,4 +1,5 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module comments.json
 enum Status ['good', 'bad', 'ugly']
diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out
index 23bf8c71ab..cd28721568 100644
--- a/tests/qapi-schema/doc-bad-section.out
+++ b/tests/qapi-schema/doc-bad-section.out
@@ -1,6 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module doc-bad-section.json
 enum Enum ['one', 'two']
 doc symbol=Enum
     body=
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 0c07301f07..430b5a87db 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -1,6 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module doc-good.json
 enum Enum ['one', 'two']
 object Base
     member base1: Enum optional=False
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index 110571b793..88c0964917 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -1,5 +1,6 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module event-case.json
 event oops None
    boxed=False
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 8336aa7629..ee3b34e623 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,6 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module ident-with-escape.json
 object q_obj_fooA-arg
     member bar1: str optional=False
 command fooA q_obj_fooA-arg -> None
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
index 0261ddf202..ebbabd7a18 100644
--- a/tests/qapi-schema/include-relpath.out
+++ b/tests/qapi-schema/include-relpath.out
@@ -1,4 +1,9 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module include-relpath.json
+include include/relpath.json
+module include/relpath.json
+include include-relpath-sub.json
+module include-relpath-sub.json
 enum Status ['good', 'bad', 'ugly']
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
index 0261ddf202..7235e055bc 100644
--- a/tests/qapi-schema/include-repetition.out
+++ b/tests/qapi-schema/include-repetition.out
@@ -1,4 +1,14 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module include-repetition.json
+include comments.json
+module comments.json
 enum Status ['good', 'bad', 'ugly']
+module include-repetition.json
+include include-repetition-sub.json
+module include-repetition-sub.json
+include comments.json
+include comments.json
+module include-repetition.json
+include comments.json
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
index 0261ddf202..006f723eeb 100644
--- a/tests/qapi-schema/include-simple.out
+++ b/tests/qapi-schema/include-simple.out
@@ -1,4 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module include-simple.json
+include include-simple-sub.json
+module include-simple-sub.json
 enum Status ['good', 'bad', 'ugly']
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index 34de8be426..a79935e8c3 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -1,6 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module indented-expr.json
 command eins None -> None
    gen=True success_response=True boxed=False
 command zwei None -> None
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 50706b0136..012e7fc06a 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -1,6 +1,7 @@
 object q_empty
 enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
     prefix QTYPE
+module qapi-schema-test.json
 object TestStruct
     member integer: int optional=False
     member boolean: bool optional=False
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 4da14b43af..67e417e298 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -16,6 +16,13 @@ from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
+
+    def visit_module(self, name):
+        print('module %s' % name)
+
+    def visit_include(self, name, info):
+        print('include %s' % name)
+
     def visit_enum_type(self, name, info, values, prefix):
         print('enum %s %s' % (name, values))
         if prefix:
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (16 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 20:56   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
                   ` (13 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

All generated .c are named like their .h, except for qmp-marshal.c and
qmp-commands.h.  To add to the confusion, tests-qmp-commands.c falsely
matches generated test-qmp-commands.h.

Get rid of this unnecessary complication.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore                                     |  3 +--
 Makefile                                       |  6 +++---
 Makefile.objs                                  |  2 +-
 docs/devel/qapi-code-gen.txt                   |  6 +++---
 qga/Makefile.objs                              |  2 +-
 scripts/qapi/commands.py                       |  2 +-
 tests/.gitignore                               |  5 ++---
 tests/Makefile.include                         | 10 +++++-----
 tests/{test-qmp-commands.c => test-qmp-cmds.c} |  0
 9 files changed, 17 insertions(+), 19 deletions(-)
 rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (100%)

diff --git a/.gitignore b/.gitignore
index 2f9a92f6cc..7d783e6e66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,9 +33,8 @@
 /qapi-visit.[ch]
 /qapi-event.[ch]
 /qapi-doc.texi
-/qmp-commands.h
+/qmp-commands.[ch]
 /qmp-introspect.[ch]
-/qmp-marshal.c
 /qemu-doc.html
 /qemu-doc.info
 /qemu-doc.txt
diff --git a/Makefile b/Makefile
index bd781c6aad..164a38578e 100644
--- a/Makefile
+++ b/Makefile
@@ -91,7 +91,7 @@ include $(SRC_PATH)/rules.mak
 
 GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
 GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
-GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
+GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
 GENERATED_FILES += qmp-introspect.h
 GENERATED_FILES += qmp-introspect.c
 GENERATED_FILES += qapi-doc.texi
@@ -496,7 +496,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
 
 qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
 qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
-qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \
+qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
 qga/qapi-generated/qga-qapi-doc.texi: \
 qga/qapi-generated/qapi-gen-timestamp ;
 qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
@@ -522,7 +522,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
 
 qapi-types.c qapi-types.h \
 qapi-visit.c qapi-visit.h \
-qmp-commands.h qmp-marshal.c \
+qmp-commands.h qmp-commands.c \
 qapi-event.c qapi-event.h \
 qmp-introspect.h qmp-introspect.c \
 qapi-doc.texi: \
diff --git a/Makefile.objs b/Makefile.objs
index 2efba6d768..d255aaf194 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -78,7 +78,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
 ######################################################################
 # qapi
 
-common-obj-y += qmp-marshal.o
+common-obj-y += qmp-commands.o
 common-obj-y += qmp-introspect.o
 common-obj-y += qmp.o hmp.o
 endif
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 1a1cbaea7b..ba1dc73298 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -1147,8 +1147,8 @@ declares qmp_COMMAND() that the user must implement.
 
 The following files are generated:
 
-$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each
-                        QMP command defined in the schema
+$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
+                         QMP command defined in the schema
 
 $(prefix)qmp-commands.h: Function prototypes for the QMP commands
                          specified in the schema
@@ -1170,7 +1170,7 @@ Example:
     void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
 
     #endif
-    $ cat qapi-generated/example-qmp-marshal.c
+    $ cat qapi-generated/example-qmp-commands.c
 [Uninteresting stuff omitted...]
 
     static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 1c5986c0bb..6151378ae4 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
 qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
 qga-obj-$(CONFIG_WIN32) += vss-win32.o
 qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
-qga-obj-y += qapi-generated/qga-qmp-marshal.o
+qga-obj-y += qapi-generated/qga-qmp-commands.o
 
 qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index a744611d58..05fe33a03b 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -289,5 +289,5 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
     schema.visit(vis)
     genc.add(vis.defn)
     genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qmp-marshal.c')
+    genc.write(output_dir, prefix + 'qmp-commands.c')
     genh.write(output_dir, prefix + 'qmp-commands.h')
diff --git a/tests/.gitignore b/tests/.gitignore
index e5c744b7ed..2629cfc2f9 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -70,13 +70,12 @@ test-qdist
 test-qga
 test-qht
 test-qht-par
-test-qmp-commands
-test-qmp-commands.h
+test-qmp-cmds
+test-qmp-commands.[ch]
 test-qmp-event
 test-qobject-input-strict
 test-qobject-input-visitor
 test-qmp-introspect.[ch]
-test-qmp-marshal.c
 test-qobject-output-visitor
 test-rcu-list
 test-replication
diff --git a/tests/Makefile.include b/tests/Makefile.include
index b406531b34..9a21ed7ee9 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -61,8 +61,8 @@ check-unit-y += tests/test-clone-visitor$(EXESUF)
 gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
 check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
 gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
-check-unit-y += tests/test-qmp-commands$(EXESUF)
-gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
+check-unit-y += tests/test-qmp-cmds$(EXESUF)
+gcov-files-test-qmp-cmds-y = qapi/qmp-dispatch.c
 check-unit-y += tests/test-string-input-visitor$(EXESUF)
 gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
 check-unit-y += tests/test-string-output-visitor$(EXESUF)
@@ -576,7 +576,7 @@ test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
 	tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
 	tests/test-clone-visitor.o \
 	tests/test-qobject-input-visitor.o \
-	tests/test-qmp-commands.o tests/test-visitor-serialization.o \
+	tests/test-qmp-cmds.o tests/test-visitor-serialization.o \
 	tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
 	tests/test-opts-visitor.o tests/test-qmp-event.o \
 	tests/rcutorture.o tests/test-rcu-list.o \
@@ -656,7 +656,7 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
 
 tests/test-qapi-types.c tests/test-qapi-types.h \
 tests/test-qapi-visit.c tests/test-qapi-visit.h \
-tests/test-qmp-commands.h tests/test-qmp-marshal.c \
+tests/test-qmp-commands.h tests/test-qmp-commands.c \
 tests/test-qapi-event.c tests/test-qapi-event.h \
 tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
 tests/test-qapi-gen-timestamp ;
@@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
 tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
 tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
 tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
-tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
+tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
 tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
 tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
 
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-cmds.c
similarity index 100%
rename from tests/test-qmp-commands.c
rename to tests/test-qmp-cmds.c
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (17 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 21:06   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
                   ` (12 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The use of QAPIGen is rather shallow so far: most of the output
accumulation is not converted.  Take the next step: convert output
accumulation in the code-generating visitor classes.  Helper functions
outside these classes are not converted.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 scripts/qapi/commands.py   | 71 ++++++++++++++++------------------------
 scripts/qapi/common.py     | 13 ++++++++
 scripts/qapi/doc.py        | 74 ++++++++++++++++++++----------------------
 scripts/qapi/events.py     | 55 ++++++++++++-------------------
 scripts/qapi/introspect.py | 56 +++++++++++++-------------------
 scripts/qapi/types.py      | 81 +++++++++++++++++++---------------------------
 scripts/qapi/visit.py      | 80 +++++++++++++++++++--------------------------
 7 files changed, 188 insertions(+), 242 deletions(-)

diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 05fe33a03b..46757db771 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -223,44 +223,15 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
     return ret
 
 
-class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
+class QAPISchemaGenCommandVisitor(QAPISchemaMonolithicCVisitor):
+
     def __init__(self, prefix):
-        self._prefix = prefix
-        self.decl = None
-        self.defn = None
-        self._regy = None
-        self._visited_ret_types = None
-
-    def visit_begin(self, schema):
-        self.decl = ''
-        self.defn = ''
+        QAPISchemaMonolithicCVisitor.__init__(
+            self, prefix, 'qmp-commands',
+            ' * Schema-defined QAPI/QMP commands', __doc__)
         self._regy = ''
         self._visited_ret_types = set()
-
-    def visit_end(self):
-        self.defn += gen_registry(self._regy, self._prefix)
-        self._regy = None
-        self._visited_ret_types = None
-
-    def visit_command(self, name, info, arg_type, ret_type,
-                      gen, success_response, boxed):
-        if not gen:
-            return
-        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
-        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)
-
-
-def gen_commands(schema, output_dir, prefix):
-    blurb = ' * Schema-defined QAPI/QMP commands'
-    genc = QAPIGenC(blurb, __doc__)
-    genh = QAPIGenH(blurb, __doc__)
-
-    genc.add(mcgen('''
+        self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/module.h"
@@ -275,19 +246,33 @@ def gen_commands(schema, output_dir, prefix):
 #include "%(prefix)sqmp-commands.h"
 
 ''',
-                   prefix=prefix))
-
-    genh.add(mcgen('''
+                             prefix=prefix))
+        self._genh.add(mcgen('''
 #include "%(prefix)sqapi-types.h"
 #include "qapi/qmp/dispatch.h"
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-                   prefix=prefix, c_prefix=c_name(prefix, protect=False)))
+                             prefix=prefix,
+                             c_prefix=c_name(prefix, protect=False)))
 
+    def visit_end(self):
+        self._genc.add(gen_registry(self._regy, self._prefix))
+
+    def visit_command(self, name, info, arg_type, ret_type,
+                      gen, success_response, boxed):
+        if not gen:
+            return
+        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
+        if ret_type and ret_type not in self._visited_ret_types:
+            self._visited_ret_types.add(ret_type)
+            self._genc.add(gen_marshal_output(ret_type))
+        self._genh.add(gen_marshal_decl(name))
+        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
+        self._regy += gen_register_command(name, success_response)
+
+
+def gen_commands(schema, output_dir, prefix):
     vis = QAPISchemaGenCommandVisitor(prefix)
     schema.visit(vis)
-    genc.add(vis.defn)
-    genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qmp-commands.c')
-    genh.write(output_dir, prefix + 'qmp-commands.h')
+    vis.write(output_dir)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 29d98ca934..31d2f73e7e 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2049,3 +2049,16 @@ class QAPIGenDoc(QAPIGen):
     def _top(self, fname):
         return (QAPIGen._top(self, fname)
                 + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
+
+
+class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
+
+    def __init__(self, prefix, what, blurb, pydoc):
+        self._prefix = prefix
+        self._what = what
+        self._genc = QAPIGenC(blurb, pydoc)
+        self._genh = QAPIGenH(blurb, pydoc)
+
+    def write(self, output_dir):
+        self._genc.write(output_dir, self._prefix + self._what + '.c')
+        self._genh.write(output_dir, self._prefix + self._what + '.h')
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index cc4d5a43fb..0ea68bf813 100644
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -197,33 +197,35 @@ def texi_entity(doc, what, base=None, variants=None,
 
 
 class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
-    def __init__(self):
-        self.out = None
+    def __init__(self, prefix):
+        self._prefix = prefix
+        self._gen = qapi.common.QAPIGenDoc()
         self.cur_doc = None
 
-    def visit_begin(self, schema):
-        self.out = ''
+    def write(self, output_dir):
+        self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
 
     def visit_enum_type(self, name, info, values, prefix):
         doc = self.cur_doc
-        self.out += TYPE_FMT(type='Enum',
-                             name=doc.symbol,
-                             body=texi_entity(doc, 'Values',
-                                              member_func=texi_enum_value))
+        self._gen.add(TYPE_FMT(type='Enum',
+                               name=doc.symbol,
+                               body=texi_entity(doc, 'Values',
+                                                member_func=texi_enum_value)))
 
     def visit_object_type(self, name, info, base, members, variants):
         doc = self.cur_doc
         if base and base.is_implicit():
             base = None
-        self.out += TYPE_FMT(type='Object',
-                             name=doc.symbol,
-                             body=texi_entity(doc, 'Members', base, variants))
+        self._gen.add(TYPE_FMT(type='Object',
+                               name=doc.symbol,
+                               body=texi_entity(doc, 'Members',
+                                                base, variants)))
 
     def visit_alternate_type(self, name, info, variants):
         doc = self.cur_doc
-        self.out += TYPE_FMT(type='Alternate',
-                             name=doc.symbol,
-                             body=texi_entity(doc, 'Members'))
+        self._gen.add(TYPE_FMT(type='Alternate',
+                               name=doc.symbol,
+                               body=texi_entity(doc, 'Members')))
 
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed):
@@ -235,44 +237,38 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
             body += texi_sections(doc)
         else:
             body = texi_entity(doc, 'Arguments')
-        self.out += MSG_FMT(type='Command',
-                            name=doc.symbol,
-                            body=body)
+        self._gen.add(MSG_FMT(type='Command',
+                              name=doc.symbol,
+                              body=body))
 
     def visit_event(self, name, info, arg_type, boxed):
         doc = self.cur_doc
-        self.out += MSG_FMT(type='Event',
-                            name=doc.symbol,
-                            body=texi_entity(doc, 'Arguments'))
+        self._gen.add(MSG_FMT(type='Event',
+                              name=doc.symbol,
+                              body=texi_entity(doc, 'Arguments')))
 
     def symbol(self, doc, entity):
-        if self.out:
-            self.out += '\n'
+        if self._gen._body:
+            self._gen.add('\n')
         self.cur_doc = doc
         entity.visit(self)
         self.cur_doc = None
 
     def freeform(self, doc):
         assert not doc.args
-        if self.out:
-            self.out += '\n'
-        self.out += texi_body(doc) + texi_sections(doc)
+        if self._gen._body:
+            self._gen.add('\n')
+        self._gen.add(texi_body(doc) + texi_sections(doc))
 
 
-def texi_schema(schema):
-    """Convert QAPI schema documentation to Texinfo"""
-    gen = QAPISchemaGenDocVisitor()
-    gen.visit_begin(schema)
+def gen_doc(schema, output_dir, prefix):
+    if not qapi.common.doc_required:
+        return
+    vis = QAPISchemaGenDocVisitor(prefix)
+    vis.visit_begin(schema)
     for doc in schema.docs:
         if doc.symbol:
-            gen.symbol(doc, schema.lookup_entity(doc.symbol))
+            vis.symbol(doc, schema.lookup_entity(doc.symbol))
         else:
-            gen.freeform(doc)
-    return gen.out
-
-
-def gen_doc(schema, output_dir, prefix):
-    if qapi.common.doc_required:
-        gen = qapi.common.QAPIGenDoc()
-        gen.add(texi_schema(schema))
-        gen.write(output_dir, prefix + 'qapi-doc.texi')
+            vis.freeform(doc)
+    vis.write(output_dir)
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index b7dc82004f..81ab3abb30 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -148,35 +148,15 @@ out:
     return ret
 
 
-class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
+class QAPISchemaGenEventVisitor(QAPISchemaMonolithicCVisitor):
+
     def __init__(self, prefix):
+        QAPISchemaMonolithicCVisitor.__init__(
+            self, prefix, 'qapi-event',
+            ' * Schema-defined QAPI/QMP events', __doc__)
         self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
-        self.decl = None
-        self.defn = None
-        self._event_names = None
-
-    def visit_begin(self, schema):
-        self.decl = ''
-        self.defn = ''
         self._event_names = []
-
-    def visit_end(self):
-        self.decl += gen_enum(self._enum_name, self._event_names)
-        self.defn += gen_enum_lookup(self._enum_name, self._event_names)
-        self._event_names = None
-
-    def visit_event(self, name, info, arg_type, boxed):
-        self.decl += gen_event_send_decl(name, arg_type, boxed)
-        self.defn += gen_event_send(name, arg_type, boxed, self._enum_name)
-        self._event_names.append(name)
-
-
-def gen_events(schema, output_dir, prefix):
-    blurb = ' * Schema-defined QAPI/QMP events'
-    genc = QAPIGenC(blurb, __doc__)
-    genh = QAPIGenH(blurb, __doc__)
-
-    genc.add(mcgen('''
+        self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "%(prefix)sqapi-event.h"
@@ -187,18 +167,25 @@ def gen_events(schema, output_dir, prefix):
 #include "qapi/qmp-event.h"
 
 ''',
-                   prefix=prefix))
-
-    genh.add(mcgen('''
+                             prefix=prefix))
+        self._genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                   prefix=prefix))
+                             prefix=prefix))
 
+    def visit_end(self):
+        self._genh.add(gen_enum(self._enum_name, self._event_names))
+        self._genc.add(gen_enum_lookup(self._enum_name, self._event_names))
+
+    def visit_event(self, name, info, arg_type, boxed):
+        self._genh.add(gen_event_send_decl(name, arg_type, boxed))
+        self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
+        self._event_names.append(name)
+
+
+def gen_events(schema, output_dir, prefix):
     vis = QAPISchemaGenEventVisitor(prefix)
     schema.visit(vis)
-    genc.add(vis.defn)
-    genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qapi-event.c')
-    genh.write(output_dir, prefix + 'qapi-event.h')
+    vis.write(output_dir)
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 1e4f065164..f571cc134c 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -40,22 +40,26 @@ def to_c_string(string):
     return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
 
 
-class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
+class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
+
     def __init__(self, prefix, unmask):
-        self._prefix = prefix
+        QAPISchemaMonolithicCVisitor.__init__(
+            self, prefix, 'qmp-introspect',
+            ' * QAPI/QMP schema introspection', __doc__)
         self._unmask = unmask
-        self.defn = None
-        self.decl = None
         self._schema = None
-        self._jsons = None
-        self._used_types = None
-        self._name_map = None
+        self._jsons = []
+        self._used_types = []
+        self._name_map = {}
+        self._genc.add(mcgen('''
+#include "qemu/osdep.h"
+#include "%(prefix)sqmp-introspect.h"
+
+''',
+                             prefix=prefix))
 
     def visit_begin(self, schema):
         self._schema = schema
-        self._jsons = []
-        self._used_types = []
-        self._name_map = {}
 
     def visit_end(self):
         # visit the types that are actually used
@@ -67,21 +71,21 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
         # TODO can generate awfully long lines
         jsons.extend(self._jsons)
         name = c_name(self._prefix, protect=False) + 'qmp_schema_json'
-        self.decl = mcgen('''
+        self._genh.add(mcgen('''
 extern const char %(c_name)s[];
 ''',
-                          c_name=c_name(name))
+                             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('''
+        self._genc.add(mcgen('''
 const char %(c_name)s[] = %(c_string)s;
 ''',
-                          c_name=c_name(name),
-                          c_string=c_string)
+                             c_name=c_name(name),
+                             c_string=c_string))
         self._schema = None
-        self._jsons = None
-        self._used_types = None
-        self._name_map = None
+        self._jsons = []
+        self._used_types = []
+        self._name_map = {}
 
     def visit_needed(self, entity):
         # Ignore types on first pass; visit_end() will pick up used types
@@ -169,20 +173,6 @@ const char %(c_name)s[] = %(c_string)s;
 
 
 def gen_introspect(schema, output_dir, prefix, opt_unmask):
-    blurb = ' * QAPI/QMP schema introspection'
-    genc = QAPIGenC(blurb, __doc__)
-    genh = QAPIGenH(blurb, __doc__)
-
-    genc.add(mcgen('''
-#include "qemu/osdep.h"
-#include "%(prefix)sqmp-introspect.h"
-
-''',
-                   prefix=prefix))
-
     vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
     schema.visit(vis)
-    genc.add(vis.defn)
-    genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qmp-introspect.c')
-    genh.write(output_dir, prefix + 'qmp-introspect.h')
+    vis.write(output_dir)
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index aa3c01e750..d2b8423479 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -167,36 +167,41 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
     return ret
 
 
-class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
-    def __init__(self, opt_builtins):
+class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
+
+    def __init__(self, prefix, opt_builtins):
+        QAPISchemaMonolithicCVisitor.__init__(
+            self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
+            __doc__)
         self._opt_builtins = opt_builtins
-        self.decl = None
-        self.defn = None
-        self._fwdecl = None
-        self._btin = None
+        self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "qapi/dealloc-visitor.h"
+#include "%(prefix)sqapi-types.h"
+#include "%(prefix)sqapi-visit.h"
+''',
+                                      prefix=prefix))
+        self._genh.preamble_add(mcgen('''
+#include "qapi/util.h"
+'''))
+        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
 
     def visit_begin(self, schema):
         # gen_object() is recursive, ensure it doesn't visit the empty type
         objects_seen.add(schema.the_empty_object_type.name)
-        self.decl = ''
-        self.defn = ''
-        self._fwdecl = ''
-        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
 
     def visit_end(self):
-        self.decl = self._fwdecl + self.decl
-        self._fwdecl = None
         # To avoid header dependency hell, we always generate
         # declarations for built-in types in our header files and
         # simply guard them.  See also opt_builtins (command line
         # option -b).
         self._btin += guardend('QAPI_TYPES_BUILTIN')
-        self.decl = self._btin + self.decl
+        self._genh.preamble_add(self._btin)
         self._btin = None
 
     def _gen_type_cleanup(self, name):
-        self.decl += gen_type_cleanup_decl(name)
-        self.defn += gen_type_cleanup(name)
+        self._genh.add(gen_type_cleanup_decl(name))
+        self._genc.add(gen_type_cleanup(name))
 
     def visit_enum_type(self, name, info, values, prefix):
         # Special case for our lone builtin enum type
@@ -204,10 +209,10 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         if not info:
             self._btin += gen_enum(name, values, prefix)
             if self._opt_builtins:
-                self.defn += gen_enum_lookup(name, values, prefix)
+                self._genc.add(gen_enum_lookup(name, values, prefix))
         else:
-            self._fwdecl += gen_enum(name, values, prefix)
-            self.defn += gen_enum_lookup(name, values, prefix)
+            self._genh.preamble_add(gen_enum(name, values, prefix))
+            self._genc.add(gen_enum_lookup(name, values, prefix))
 
     def visit_array_type(self, name, info, element_type):
         if isinstance(element_type, QAPISchemaBuiltinType):
@@ -215,20 +220,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
             self._btin += gen_array(name, element_type)
             self._btin += gen_type_cleanup_decl(name)
             if self._opt_builtins:
-                self.defn += gen_type_cleanup(name)
+                self._genc.add(gen_type_cleanup(name))
         else:
-            self._fwdecl += gen_fwd_object_or_array(name)
-            self.decl += gen_array(name, element_type)
+            self._genh.preamble_add(gen_fwd_object_or_array(name))
+            self._genh.add(gen_array(name, element_type))
             self._gen_type_cleanup(name)
 
     def visit_object_type(self, name, info, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self._fwdecl += gen_fwd_object_or_array(name)
-        self.decl += gen_object(name, base, members, variants)
+        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_object(name, base, members, variants))
         if base and not base.is_implicit():
-            self.decl += gen_upcast(name, base)
+            self._genh.add(gen_upcast(name, base))
         # TODO Worth changing the visitor signature, so we could
         # directly use rather than repeat type.is_implicit()?
         if not name.startswith('q_'):
@@ -236,31 +241,13 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
             self._gen_type_cleanup(name)
 
     def visit_alternate_type(self, name, info, variants):
-        self._fwdecl += gen_fwd_object_or_array(name)
-        self.decl += gen_object(name, None, [variants.tag_member], variants)
+        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_object(name, None,
+                                  [variants.tag_member], variants))
         self._gen_type_cleanup(name)
 
 
 def gen_types(schema, output_dir, prefix, opt_builtins):
-    blurb = ' * Schema-defined QAPI types'
-    genc = QAPIGenC(blurb, __doc__)
-    genh = QAPIGenH(blurb, __doc__)
-
-    genc.add(mcgen('''
-#include "qemu/osdep.h"
-#include "qapi/dealloc-visitor.h"
-#include "%(prefix)sqapi-types.h"
-#include "%(prefix)sqapi-visit.h"
-''',
-                   prefix=prefix))
-
-    genh.add(mcgen('''
-#include "qapi/util.h"
-'''))
-
-    vis = QAPISchemaGenTypeVisitor(opt_builtins)
+    vis = QAPISchemaGenTypeVisitor(prefix, opt_builtins)
     schema.visit(vis)
-    genc.add(vis.defn)
-    genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qapi-types.c')
-    genh.write(output_dir, prefix + 'qapi-types.h')
+    vis.write(output_dir)
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index f966e7975f..3d09d44265 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -263,16 +263,27 @@ out:
                  c_name=c_name(name))
 
 
-class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
-    def __init__(self, opt_builtins):
+class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
+
+    def __init__(self, prefix, opt_builtins):
+        QAPISchemaMonolithicCVisitor.__init__(
+            self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
+            __doc__)
         self._opt_builtins = opt_builtins
-        self.decl = None
-        self.defn = None
-        self._btin = None
+        self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "%(prefix)sqapi-visit.h"
+''',
+                                      prefix=prefix))
+        self._genh.preamble_add(mcgen('''
+#include "qapi/visitor.h"
+#include "%(prefix)sqapi-types.h"
 
-    def visit_begin(self, schema):
-        self.decl = ''
-        self.defn = ''
+''',
+                                      prefix=prefix))
         self._btin = guardstart('QAPI_VISIT_BUILTIN')
 
     def visit_end(self):
@@ -281,7 +292,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         # simply guard them.  See also opt_builtins (command line
         # option -b).
         self._btin += guardend('QAPI_VISIT_BUILTIN')
-        self.decl = self._btin + self.decl
+        self._genh.preamble_add(self._btin)
         self._btin = None
 
     def visit_enum_type(self, name, info, values, prefix):
@@ -290,10 +301,10 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         if not info:
             self._btin += gen_visit_decl(name, scalar=True)
             if self._opt_builtins:
-                self.defn += gen_visit_enum(name)
+                self._genc.add(gen_visit_enum(name))
         else:
-            self.decl += gen_visit_decl(name, scalar=True)
-            self.defn += gen_visit_enum(name)
+            self._genh.add(gen_visit_decl(name, scalar=True))
+            self._genc.add(gen_visit_enum(name))
 
     def visit_array_type(self, name, info, element_type):
         decl = gen_visit_decl(name)
@@ -301,53 +312,30 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
         if isinstance(element_type, QAPISchemaBuiltinType):
             self._btin += decl
             if self._opt_builtins:
-                self.defn += defn
+                self._genc.add(defn)
         else:
-            self.decl += decl
-            self.defn += defn
+            self._genh.add(decl)
+            self._genc.add(defn)
 
     def visit_object_type(self, name, info, base, members, variants):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
-        self.decl += gen_visit_members_decl(name)
-        self.defn += gen_visit_object_members(name, base, members, variants)
+        self._genh.add(gen_visit_members_decl(name))
+        self._genc.add(gen_visit_object_members(name, base, members, variants))
         # TODO Worth changing the visitor signature, so we could
         # directly use rather than repeat type.is_implicit()?
         if not name.startswith('q_'):
             # only explicit types need an allocating visit
-            self.decl += gen_visit_decl(name)
-            self.defn += gen_visit_object(name, base, members, variants)
+            self._genh.add(gen_visit_decl(name))
+            self._genc.add(gen_visit_object(name, base, members, variants))
 
     def visit_alternate_type(self, name, info, variants):
-        self.decl += gen_visit_decl(name)
-        self.defn += gen_visit_alternate(name, variants)
+        self._genh.add(gen_visit_decl(name))
+        self._genc.add(gen_visit_alternate(name, variants))
 
 
 def gen_visit(schema, output_dir, prefix, opt_builtins):
-    blurb = ' * Schema-defined QAPI visitors'
-    genc = QAPIGenC(blurb, __doc__)
-    genh = QAPIGenH(blurb, __doc__)
-
-    genc.add(mcgen('''
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "qapi/error.h"
-#include "qapi/qmp/qerror.h"
-#include "%(prefix)sqapi-visit.h"
-''',
-                   prefix=prefix))
-
-    genh.add(mcgen('''
-#include "qapi/visitor.h"
-#include "%(prefix)sqapi-types.h"
-
-''',
-                   prefix=prefix))
-
-    vis = QAPISchemaGenVisitVisitor(opt_builtins)
+    vis = QAPISchemaGenVisitVisitor(prefix, opt_builtins)
     schema.visit(vis)
-    genc.add(vis.defn)
-    genh.add(vis.decl)
-    genc.write(output_dir, prefix + 'qapi-visit.c')
-    genh.write(output_dir, prefix + 'qapi-visit.h')
+    vis.write(output_dir)
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (18 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-12 21:44   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames Markus Armbruster
                   ` (11 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Linking code from multiple separate QAPI schemata into the same
program is possible, but involves some weirdness around built-in
types:

* We generate code for built-in types into .c only with option
  --builtins.  The user is responsible for generating code for exactly
  one QAPI schema per program with --builtins.

* We generate code for built-in types into .h regardless of
  --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN.  Because all
  copies of this code are exactly the same, including any combination
  of these headers works.

Replace this contraption by something more conventional: generate code
for built-in types into their very own files: qapi-builtin-types.c,
qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
only with --builtins.  Obey --output-dir, but ignore --prefix for
them.

Make qapi-types.h include qapi-builtin-types.h.  With multiple
schemata you now have multiple qapi-types.[ch], but only one
qapi-builtin-types.[ch].  Same for qapi-visit.[ch] and
qapi-builtin-visit.[ch].

Bonus: if all you need is built-in stuff, you can include a much
smaller header.  To be exploited shortly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore             |  2 ++
 Makefile               | 13 ++++++----
 Makefile.objs          |  2 ++
 scripts/qapi/common.py | 61 ++++++++++++++++++++++++++++++++++++++++-------
 scripts/qapi/types.py  | 61 +++++++++++++++++++----------------------------
 scripts/qapi/visit.py  | 64 +++++++++++++++++++++-----------------------------
 6 files changed, 116 insertions(+), 87 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7d783e6e66..9477a08b6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,8 @@
 /qga/qapi-generated
 /qapi-generated
 /qapi-gen-timestamp
+/qapi-builtin-types.[ch]
+/qapi-builtin-visit.[ch]
 /qapi-types.[ch]
 /qapi-visit.[ch]
 /qapi-event.[ch]
diff --git a/Makefile b/Makefile
index 164a38578e..60ddc9c945 100644
--- a/Makefile
+++ b/Makefile
@@ -90,10 +90,13 @@ endif
 include $(SRC_PATH)/rules.mak
 
 GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
-GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
-GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
-GENERATED_FILES += qmp-introspect.h
-GENERATED_FILES += qmp-introspect.c
+GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
+GENERATED_FILES += qapi-types.h qapi-types.c
+GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
+GENERATED_FILES += qapi-visit.h qapi-visit.c
+GENERATED_FILES += qmp-commands.h qmp-commands.c
+GENERATED_FILES += qapi-event.h qapi-event.c
+GENERATED_FILES += qmp-introspect.c qmp-introspect.h
 GENERATED_FILES += qapi-doc.texi
 
 GENERATED_FILES += trace/generated-tcg-tracers.h
@@ -520,7 +523,9 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/transaction.json \
                $(SRC_PATH)/qapi/ui.json
 
+qapi-builtin-types.c qapi-builtin-types.h \
 qapi-types.c qapi-types.h \
+qapi-builtin-visit.c qapi-builtin-visit.h \
 qapi-visit.c qapi-visit.h \
 qmp-commands.h qmp-commands.c \
 qapi-event.c qapi-event.h \
diff --git a/Makefile.objs b/Makefile.objs
index d255aaf194..2813e984fd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -2,6 +2,8 @@
 # Common libraries for tools and emulators
 stub-obj-y = stubs/ crypto/
 util-obj-y = util/ qobject/ qapi/
+util-obj-y += qapi-builtin-types.o
+util-obj-y += qapi-builtin-visit.o
 util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
 
 chardev-obj-y = chardev/
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 31d2f73e7e..de12f8469a 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1531,11 +1531,10 @@ class QAPISchema(object):
 
     def _def_builtin_type(self, name, json_type, c_type):
         self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
-        # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
-        # qapi-types.h from a single .c, all arrays of builtins must be
-        # declared in the first file whether or not they are used.  Nicer
-        # would be to use lazy instantiation, while figuring out how to
-        # avoid compilation issues with multiple qapi-types.h.
+        # Instantiating only the arrays that are actually used would
+        # be nice, but we can't as long as their generated code
+        # (qapi-builtin-types.[ch]) may be shared by some other
+        # schema.
         self._make_array_type(name, None)
 
     def _def_predefineds(self):
@@ -1992,14 +1991,15 @@ class QAPIGen(object):
         return ''
 
     def write(self, output_dir, fname):
-        if output_dir:
+        pathname = os.path.join(output_dir, fname)
+        dir = os.path.dirname(pathname)
+        if dir:
             try:
-                os.makedirs(output_dir)
+                os.makedirs(dir)
             except os.error as e:
                 if e.errno != errno.EEXIST:
                     raise
-        fd = os.open(os.path.join(output_dir, fname),
-                     os.O_RDWR | os.O_CREAT, 0666)
+        fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0666)
         f = os.fdopen(fd, 'r+')
         text = (self._top(fname) + self._preamble + self._body
                 + self._bottom(fname))
@@ -2046,6 +2046,7 @@ class QAPIGenH(QAPIGenC):
 
 
 class QAPIGenDoc(QAPIGen):
+
     def _top(self, fname):
         return (QAPIGen._top(self, fname)
                 + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
@@ -2062,3 +2063,45 @@ class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
     def write(self, output_dir):
         self._genc.write(output_dir, self._prefix + self._what + '.c')
         self._genh.write(output_dir, self._prefix + self._what + '.h')
+
+
+class QAPISchemaModularCVisitor(QAPISchemaVisitor):
+
+    def __init__(self, prefix, what, blurb, pydoc):
+        self._prefix = prefix
+        self._what = what
+        self._blurb = blurb
+        self._pydoc = pydoc
+        self._module = {}
+
+    def _module_basename(self, what, name):
+        if name is None:
+            return re.sub(r'-', '-builtin-', what)
+        return self._prefix + what
+
+    def _add_module(self, name, blurb):
+        genc = QAPIGenC(blurb, self._pydoc)
+        genh = QAPIGenH(blurb, self._pydoc)
+        self._module[name] = (genc, genh)
+        self._set_module(name)
+
+    def _set_module(self, name):
+        self._genc, self._genh = self._module[name]
+
+    def write(self, output_dir, opt_builtins):
+        for name in self._module:
+            if name is None and not opt_builtins:
+                continue
+            basename = self._module_basename(self._what, name)
+            (genc, genh) = self._module[name]
+            genc.write(output_dir, basename + '.c')
+            genh.write(output_dir, basename + '.h')
+
+    def _begin_module(self, name):
+        pass
+
+    def visit_module(self, name):
+        if len(self._module) != 1:
+            return
+        self._add_module(name, self._blurb)
+        self._begin_module(name)
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index d2b8423479..59826b1162 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -167,64 +167,51 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
     return ret
 
 
-class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
+class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
 
-    def __init__(self, prefix, opt_builtins):
-        QAPISchemaMonolithicCVisitor.__init__(
+    def __init__(self, prefix):
+        QAPISchemaModularCVisitor.__init__(
             self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
             __doc__)
-        self._opt_builtins = opt_builtins
+        self._add_module(None, ' * Built-in QAPI types')
+        self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "qapi/dealloc-visitor.h"
+#include "qapi-builtin-types.h"
+#include "qapi-builtin-visit.h"
+'''))
+        self._genh.preamble_add(mcgen('''
+#include "qapi/util.h"
+'''))
+
+    def _begin_module(self, name):
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
 #include "%(prefix)sqapi-types.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                                      prefix=prefix))
+                                      prefix=self._prefix))
         self._genh.preamble_add(mcgen('''
-#include "qapi/util.h"
+#include "qapi-builtin-types.h"
 '''))
-        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
 
     def visit_begin(self, schema):
         # gen_object() is recursive, ensure it doesn't visit the empty type
         objects_seen.add(schema.the_empty_object_type.name)
 
-    def visit_end(self):
-        # To avoid header dependency hell, we always generate
-        # declarations for built-in types in our header files and
-        # simply guard them.  See also opt_builtins (command line
-        # option -b).
-        self._btin += guardend('QAPI_TYPES_BUILTIN')
-        self._genh.preamble_add(self._btin)
-        self._btin = None
-
     def _gen_type_cleanup(self, name):
         self._genh.add(gen_type_cleanup_decl(name))
         self._genc.add(gen_type_cleanup(name))
 
     def visit_enum_type(self, name, info, values, prefix):
-        # Special case for our lone builtin enum type
-        # TODO use something cleaner than existence of info
-        if not info:
-            self._btin += gen_enum(name, values, prefix)
-            if self._opt_builtins:
-                self._genc.add(gen_enum_lookup(name, values, prefix))
-        else:
-            self._genh.preamble_add(gen_enum(name, values, prefix))
-            self._genc.add(gen_enum_lookup(name, values, prefix))
+        self._genh.preamble_add(gen_enum(name, values, prefix))
+        self._genc.add(gen_enum_lookup(name, values, prefix))
 
     def visit_array_type(self, name, info, element_type):
-        if isinstance(element_type, QAPISchemaBuiltinType):
-            self._btin += gen_fwd_object_or_array(name)
-            self._btin += gen_array(name, element_type)
-            self._btin += gen_type_cleanup_decl(name)
-            if self._opt_builtins:
-                self._genc.add(gen_type_cleanup(name))
-        else:
-            self._genh.preamble_add(gen_fwd_object_or_array(name))
-            self._genh.add(gen_array(name, element_type))
-            self._gen_type_cleanup(name)
+        self._genh.preamble_add(gen_fwd_object_or_array(name))
+        self._genh.add(gen_array(name, element_type))
+        self._gen_type_cleanup(name)
 
     def visit_object_type(self, name, info, base, members, variants):
         # Nothing to do for the special empty builtin
@@ -248,6 +235,6 @@ class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
 
 
 def gen_types(schema, output_dir, prefix, opt_builtins):
-    vis = QAPISchemaGenTypeVisitor(prefix, opt_builtins)
+    vis = QAPISchemaGenTypeVisitor(prefix)
     schema.visit(vis)
-    vis.write(output_dir)
+    vis.write(output_dir, opt_builtins)
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 3d09d44265..9b678e7263 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -263,13 +263,27 @@ out:
                  c_name=c_name(name))
 
 
-class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
+class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 
-    def __init__(self, prefix, opt_builtins):
-        QAPISchemaMonolithicCVisitor.__init__(
+    def __init__(self, prefix):
+        QAPISchemaModularCVisitor.__init__(
             self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
             __doc__)
-        self._opt_builtins = opt_builtins
+        self._add_module(None, ' * Built-in QAPI visitors')
+        self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qapi-builtin-visit.h"
+'''))
+        self._genh.preamble_add(mcgen('''
+#include "qapi/visitor.h"
+#include "qapi-builtin-types.h"
+
+''',
+                                      prefix=prefix))
+
+    def _begin_module(self, name):
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -277,45 +291,21 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
 #include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                                      prefix=prefix))
+                                      prefix=self._prefix))
         self._genh.preamble_add(mcgen('''
-#include "qapi/visitor.h"
+#include "qapi-builtin-visit.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                                      prefix=prefix))
-        self._btin = guardstart('QAPI_VISIT_BUILTIN')
-
-    def visit_end(self):
-        # To avoid header dependency hell, we always generate
-        # declarations for built-in types in our header files and
-        # simply guard them.  See also opt_builtins (command line
-        # option -b).
-        self._btin += guardend('QAPI_VISIT_BUILTIN')
-        self._genh.preamble_add(self._btin)
-        self._btin = None
+                                      prefix=self._prefix))
 
     def visit_enum_type(self, name, info, values, prefix):
-        # Special case for our lone builtin enum type
-        # TODO use something cleaner than existence of info
-        if not info:
-            self._btin += gen_visit_decl(name, scalar=True)
-            if self._opt_builtins:
-                self._genc.add(gen_visit_enum(name))
-        else:
-            self._genh.add(gen_visit_decl(name, scalar=True))
-            self._genc.add(gen_visit_enum(name))
+        self._genh.add(gen_visit_decl(name, scalar=True))
+        self._genc.add(gen_visit_enum(name))
 
     def visit_array_type(self, name, info, element_type):
-        decl = gen_visit_decl(name)
-        defn = gen_visit_list(name, element_type)
-        if isinstance(element_type, QAPISchemaBuiltinType):
-            self._btin += decl
-            if self._opt_builtins:
-                self._genc.add(defn)
-        else:
-            self._genh.add(decl)
-            self._genc.add(defn)
+        self._genh.add(gen_visit_decl(name))
+        self._genc.add(gen_visit_list(name, element_type))
 
     def visit_object_type(self, name, info, base, members, variants):
         # Nothing to do for the special empty builtin
@@ -336,6 +326,6 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
 
 
 def gen_visit(schema, output_dir, prefix, opt_builtins):
-    vis = QAPISchemaGenVisitVisitor(prefix, opt_builtins)
+    vis = QAPISchemaGenVisitVisitor(prefix)
     schema.visit(vis)
-    vis.write(output_dir)
+    vis.write(output_dir, opt_builtins)
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (19 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
@ 2018-02-11  9:35 ` Markus Armbruster
  2018-02-19 18:18   ` Michael Roth
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module Markus Armbruster
                   ` (10 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

guardname() fails to return a valid C identifier for arguments
containing anything but [A-Za-z0-9_.-'].  Fix that.  Don't bother
protecting ticklish identifiers; header guards are all-caps, and no
ticklish identifiers are.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 scripts/qapi/common.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index de12f8469a..6e5152b173 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -1867,7 +1867,7 @@ def mcgen(code, **kwds):
 
 
 def guardname(filename):
-    return c_name(filename, protect=False).upper()
+    return re.sub(r'[^A-Za-z0-9_]', '_', filename).upper()
 
 
 def guardstart(name):
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (20 preceding siblings ...)
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:06   ` Eric Blake
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
                   ` (9 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Our qapi-schema.json is composed of modules connected by include
directives, but the generated code is monolithic all the same: one
qapi-types.h with all the types, one qapi-visit.h with all the
visitors, and so forth.  These monolithic headers get included all
over the place.  In my "build everything" tree, adding a QAPI type
recompiles about 4800 out of 5100 objects.

We wouldn't write such monolithic headers by hand.  It stands to
reason that we shouldn't generate them, either.

Split up generated qapi-types.h to mirror the schema's modular
structure: one header per module.  Name the main module's header
qapi-types.h, and sub-module D/B.json's header D/qapi-types-B.h.

Mirror the schema's includes in the headers, so that qapi-types.h gets
you everything exactly as before.  If you need less, you can include
one or more of the sub-module headers.  To be exploited shortly.

Split up qapi-types.c, qapi-visit.h, qapi-visit.c, qmp-commands.h,
qmp-commands.c, qapi-event.h, qapi-event.c the same way.
qmp-introspect.h, qmp-introspect.c and qapi.texi remain monolithic.

The split of qmp-commands.c duplicates static helper function
qmp_marshal_output_str() in qapi-commands-char.c and
qapi-commands-misc.c.  This happens when commands returning the same
type occur in multiple modules.  Not worth avoiding.

Since I'm going to rename qapi-event.[ch] to qapi-events.[ch], and
qmp-commands.[ch] to qapi-commands.[ch], name the shards that way
already, to reduce churn.  This requires temporary hacks in
commands.py and events.py.  They'll go away with the rename.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore               |  60 ++++++++++++++++++++++++
 Makefile                 | 120 +++++++++++++++++++++++++++++++++++++++++++++++
 Makefile.objs            |  65 ++++++++++++++++++++++++-
 scripts/qapi/commands.py |  35 +++++++++-----
 scripts/qapi/common.py   |  21 +++++++--
 scripts/qapi/events.py   |  19 ++++++--
 6 files changed, 300 insertions(+), 20 deletions(-)

diff --git a/.gitignore b/.gitignore
index 9477a08b6b..42c57998fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,7 +31,67 @@
 /qapi-gen-timestamp
 /qapi-builtin-types.[ch]
 /qapi-builtin-visit.[ch]
+/qapi/qapi-commands-block-core.[ch]
+/qapi/qapi-commands-block.[ch]
+/qapi/qapi-commands-char.[ch]
+/qapi/qapi-commands-common.[ch]
+/qapi/qapi-commands-crypto.[ch]
+/qapi/qapi-commands-introspect.[ch]
+/qapi/qapi-commands-migration.[ch]
+/qapi/qapi-commands-net.[ch]
+/qapi/qapi-commands-rocker.[ch]
+/qapi/qapi-commands-run-state.[ch]
+/qapi/qapi-commands-sockets.[ch]
+/qapi/qapi-commands-tpm.[ch]
+/qapi/qapi-commands-trace.[ch]
+/qapi/qapi-commands-transaction.[ch]
+/qapi/qapi-commands-ui.[ch]
+/qapi/qapi-events-block-core.[ch]
+/qapi/qapi-events-block.[ch]
+/qapi/qapi-events-char.[ch]
+/qapi/qapi-events-common.[ch]
+/qapi/qapi-events-crypto.[ch]
+/qapi/qapi-events-introspect.[ch]
+/qapi/qapi-events-migration.[ch]
+/qapi/qapi-events-net.[ch]
+/qapi/qapi-events-rocker.[ch]
+/qapi/qapi-events-run-state.[ch]
+/qapi/qapi-events-sockets.[ch]
+/qapi/qapi-events-tpm.[ch]
+/qapi/qapi-events-trace.[ch]
+/qapi/qapi-events-transaction.[ch]
+/qapi/qapi-events-ui.[ch]
+/qapi/qapi-types-block-core.[ch]
+/qapi/qapi-types-block.[ch]
+/qapi/qapi-types-char.[ch]
+/qapi/qapi-types-common.[ch]
+/qapi/qapi-types-crypto.[ch]
+/qapi/qapi-types-introspect.[ch]
+/qapi/qapi-types-migration.[ch]
+/qapi/qapi-types-net.[ch]
+/qapi/qapi-types-rocker.[ch]
+/qapi/qapi-types-run-state.[ch]
+/qapi/qapi-types-sockets.[ch]
+/qapi/qapi-types-tpm.[ch]
+/qapi/qapi-types-trace.[ch]
+/qapi/qapi-types-transaction.[ch]
+/qapi/qapi-types-ui.[ch]
 /qapi-types.[ch]
+/qapi/qapi-visit-block-core.[ch]
+/qapi/qapi-visit-block.[ch]
+/qapi/qapi-visit-char.[ch]
+/qapi/qapi-visit-common.[ch]
+/qapi/qapi-visit-crypto.[ch]
+/qapi/qapi-visit-introspect.[ch]
+/qapi/qapi-visit-migration.[ch]
+/qapi/qapi-visit-net.[ch]
+/qapi/qapi-visit-rocker.[ch]
+/qapi/qapi-visit-run-state.[ch]
+/qapi/qapi-visit-sockets.[ch]
+/qapi/qapi-visit-tpm.[ch]
+/qapi/qapi-visit-trace.[ch]
+/qapi/qapi-visit-transaction.[ch]
+/qapi/qapi-visit-ui.[ch]
 /qapi-visit.[ch]
 /qapi-event.[ch]
 /qapi-doc.texi
diff --git a/Makefile b/Makefile
index 60ddc9c945..ac9a7627a2 100644
--- a/Makefile
+++ b/Makefile
@@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak
 GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
 GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
 GENERATED_FILES += qapi-types.h qapi-types.c
+GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
+GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c
+GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c
+GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c
+GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c
+GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c
+GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c
+GENERATED_FILES += qapi/qapi-types-net.h qapi/qapi-types-net.c
+GENERATED_FILES += qapi/qapi-types-rocker.h qapi/qapi-types-rocker.c
+GENERATED_FILES += qapi/qapi-types-run-state.h qapi/qapi-types-run-state.c
+GENERATED_FILES += qapi/qapi-types-sockets.h qapi/qapi-types-sockets.c
+GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c
+GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c
+GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c
+GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c
 GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
 GENERATED_FILES += qapi-visit.h qapi-visit.c
+GENERATED_FILES += qapi/qapi-visit-block-core.h qapi/qapi-visit-block-core.c
+GENERATED_FILES += qapi/qapi-visit-block.h qapi/qapi-visit-block.c
+GENERATED_FILES += qapi/qapi-visit-char.h qapi/qapi-visit-char.c
+GENERATED_FILES += qapi/qapi-visit-common.h qapi/qapi-visit-common.c
+GENERATED_FILES += qapi/qapi-visit-crypto.h qapi/qapi-visit-crypto.c
+GENERATED_FILES += qapi/qapi-visit-introspect.h qapi/qapi-visit-introspect.c
+GENERATED_FILES += qapi/qapi-visit-migration.h qapi/qapi-visit-migration.c
+GENERATED_FILES += qapi/qapi-visit-net.h qapi/qapi-visit-net.c
+GENERATED_FILES += qapi/qapi-visit-rocker.h qapi/qapi-visit-rocker.c
+GENERATED_FILES += qapi/qapi-visit-run-state.h qapi/qapi-visit-run-state.c
+GENERATED_FILES += qapi/qapi-visit-sockets.h qapi/qapi-visit-sockets.c
+GENERATED_FILES += qapi/qapi-visit-tpm.h qapi/qapi-visit-tpm.c
+GENERATED_FILES += qapi/qapi-visit-trace.h qapi/qapi-visit-trace.c
+GENERATED_FILES += qapi/qapi-visit-transaction.h qapi/qapi-visit-transaction.c
+GENERATED_FILES += qapi/qapi-visit-ui.h qapi/qapi-visit-ui.c
 GENERATED_FILES += qmp-commands.h qmp-commands.c
+GENERATED_FILES += qapi/qapi-commands-block-core.h qapi/qapi-commands-block-core.c
+GENERATED_FILES += qapi/qapi-commands-block.h qapi/qapi-commands-block.c
+GENERATED_FILES += qapi/qapi-commands-char.h qapi/qapi-commands-char.c
+GENERATED_FILES += qapi/qapi-commands-common.h qapi/qapi-commands-common.c
+GENERATED_FILES += qapi/qapi-commands-crypto.h qapi/qapi-commands-crypto.c
+GENERATED_FILES += qapi/qapi-commands-introspect.h qapi/qapi-commands-introspect.c
+GENERATED_FILES += qapi/qapi-commands-migration.h qapi/qapi-commands-migration.c
+GENERATED_FILES += qapi/qapi-commands-net.h qapi/qapi-commands-net.c
+GENERATED_FILES += qapi/qapi-commands-rocker.h qapi/qapi-commands-rocker.c
+GENERATED_FILES += qapi/qapi-commands-run-state.h qapi/qapi-commands-run-state.c
+GENERATED_FILES += qapi/qapi-commands-sockets.h qapi/qapi-commands-sockets.c
+GENERATED_FILES += qapi/qapi-commands-tpm.h qapi/qapi-commands-tpm.c
+GENERATED_FILES += qapi/qapi-commands-trace.h qapi/qapi-commands-trace.c
+GENERATED_FILES += qapi/qapi-commands-transaction.h qapi/qapi-commands-transaction.c
+GENERATED_FILES += qapi/qapi-commands-ui.h qapi/qapi-commands-ui.c
 GENERATED_FILES += qapi-event.h qapi-event.c
+GENERATED_FILES += qapi/qapi-events-block-core.h qapi/qapi-events-block-core.c
+GENERATED_FILES += qapi/qapi-events-block.h qapi/qapi-events-block.c
+GENERATED_FILES += qapi/qapi-events-char.h qapi/qapi-events-char.c
+GENERATED_FILES += qapi/qapi-events-common.h qapi/qapi-events-common.c
+GENERATED_FILES += qapi/qapi-events-crypto.h qapi/qapi-events-crypto.c
+GENERATED_FILES += qapi/qapi-events-introspect.h qapi/qapi-events-introspect.c
+GENERATED_FILES += qapi/qapi-events-migration.h qapi/qapi-events-migration.c
+GENERATED_FILES += qapi/qapi-events-net.h qapi/qapi-events-net.c
+GENERATED_FILES += qapi/qapi-events-rocker.h qapi/qapi-events-rocker.c
+GENERATED_FILES += qapi/qapi-events-run-state.h qapi/qapi-events-run-state.c
+GENERATED_FILES += qapi/qapi-events-sockets.h qapi/qapi-events-sockets.c
+GENERATED_FILES += qapi/qapi-events-tpm.h qapi/qapi-events-tpm.c
+GENERATED_FILES += qapi/qapi-events-trace.h qapi/qapi-events-trace.c
+GENERATED_FILES += qapi/qapi-events-transaction.h qapi/qapi-events-transaction.c
+GENERATED_FILES += qapi/qapi-events-ui.h qapi/qapi-events-ui.c
 GENERATED_FILES += qmp-introspect.c qmp-introspect.h
 GENERATED_FILES += qapi-doc.texi
 
@@ -525,10 +585,70 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
 
 qapi-builtin-types.c qapi-builtin-types.h \
 qapi-types.c qapi-types.h \
+qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
+qapi/qapi-types-block.c qapi/qapi-types-block.h \
+qapi/qapi-types-char.c qapi/qapi-types-char.h \
+qapi/qapi-types-common.c qapi/qapi-types-common.h \
+qapi/qapi-types-crypto.c qapi/qapi-types-crypto.h \
+qapi/qapi-types-introspect.c qapi/qapi-types-introspect.h \
+qapi/qapi-types-migration.c qapi/qapi-types-migration.h \
+qapi/qapi-types-net.c qapi/qapi-types-net.h \
+qapi/qapi-types-rocker.c qapi/qapi-types-rocker.h \
+qapi/qapi-types-run-state.c qapi/qapi-types-run-state.h \
+qapi/qapi-types-sockets.c qapi/qapi-types-sockets.h \
+qapi/qapi-types-tpm.c qapi/qapi-types-tpm.h \
+qapi/qapi-types-trace.c qapi/qapi-types-trace.h \
+qapi/qapi-types-transaction.c qapi/qapi-types-transaction.h \
+qapi/qapi-types-ui.c qapi/qapi-types-ui.h \
 qapi-builtin-visit.c qapi-builtin-visit.h \
 qapi-visit.c qapi-visit.h \
+qapi/qapi-visit-block-core.c qapi/qapi-visit-block-core.h \
+qapi/qapi-visit-block.c qapi/qapi-visit-block.h \
+qapi/qapi-visit-char.c qapi/qapi-visit-char.h \
+qapi/qapi-visit-common.c qapi/qapi-visit-common.h \
+qapi/qapi-visit-crypto.c qapi/qapi-visit-crypto.h \
+qapi/qapi-visit-introspect.c qapi/qapi-visit-introspect.h \
+qapi/qapi-visit-migration.c qapi/qapi-visit-migration.h \
+qapi/qapi-visit-net.c qapi/qapi-visit-net.h \
+qapi/qapi-visit-rocker.c qapi/qapi-visit-rocker.h \
+qapi/qapi-visit-run-state.c qapi/qapi-visit-run-state.h \
+qapi/qapi-visit-sockets.c qapi/qapi-visit-sockets.h \
+qapi/qapi-visit-tpm.c qapi/qapi-visit-tpm.h \
+qapi/qapi-visit-trace.c qapi/qapi-visit-trace.h \
+qapi/qapi-visit-transaction.c qapi/qapi-visit-transaction.h \
+qapi/qapi-visit-ui.c qapi/qapi-visit-ui.h \
 qmp-commands.h qmp-commands.c \
+qapi/qapi-commands-block-core.c qapi/qapi-commands-block-core.h \
+qapi/qapi-commands-block.c qapi/qapi-commands-block.h \
+qapi/qapi-commands-char.c qapi/qapi-commands-char.h \
+qapi/qapi-commands-common.c qapi/qapi-commands-common.h \
+qapi/qapi-commands-crypto.c qapi/qapi-commands-crypto.h \
+qapi/qapi-commands-introspect.c qapi/qapi-commands-introspect.h \
+qapi/qapi-commands-migration.c qapi/qapi-commands-migration.h \
+qapi/qapi-commands-net.c qapi/qapi-commands-net.h \
+qapi/qapi-commands-rocker.c qapi/qapi-commands-rocker.h \
+qapi/qapi-commands-run-state.c qapi/qapi-commands-run-state.h \
+qapi/qapi-commands-sockets.c qapi/qapi-commands-sockets.h \
+qapi/qapi-commands-tpm.c qapi/qapi-commands-tpm.h \
+qapi/qapi-commands-trace.c qapi/qapi-commands-trace.h \
+qapi/qapi-commands-transaction.c qapi/qapi-commands-transaction.h \
+qapi/qapi-commands-ui.c qapi/qapi-commands-ui.h \
 qapi-event.c qapi-event.h \
+qapi/qapi-events-block-core.c qapi/qapi-events-block-core.h \
+qapi/qapi-events-block.c qapi/qapi-events-block.h \
+qapi/qapi-events-char.c qapi/qapi-events-char.h \
+qapi/qapi-events-common.c qapi/qapi-events-common.h \
+qapi/qapi-events-crypto.c qapi/qapi-events-crypto.h \
+qapi/qapi-events-introspect.c qapi/qapi-events-introspect.h \
+qapi/qapi-events-migration.c qapi/qapi-events-migration.h \
+qapi/qapi-events-net.c qapi/qapi-events-net.h \
+qapi/qapi-events-rocker.c qapi/qapi-events-rocker.h \
+qapi/qapi-events-run-state.c qapi/qapi-events-run-state.h \
+qapi/qapi-events-sockets.c qapi/qapi-events-sockets.h \
+qapi/qapi-events-tpm.c qapi/qapi-events-tpm.h \
+qapi/qapi-events-trace.c qapi/qapi-events-trace.h \
+qapi/qapi-events-transaction.c qapi/qapi-events-transaction.h \
+qapi/qapi-events-ui.c qapi/qapi-events-ui.h \
 qmp-introspect.h qmp-introspect.c \
 qapi-doc.texi: \
 qapi-gen-timestamp ;
diff --git a/Makefile.objs b/Makefile.objs
index 2813e984fd..7a55d45669 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -3,8 +3,56 @@
 stub-obj-y = stubs/ crypto/
 util-obj-y = util/ qobject/ qapi/
 util-obj-y += qapi-builtin-types.o
+util-obj-y += qapi-types.o
+util-obj-y += qapi/qapi-types-block-core.o
+util-obj-y += qapi/qapi-types-block.o
+util-obj-y += qapi/qapi-types-char.o
+util-obj-y += qapi/qapi-types-common.o
+util-obj-y += qapi/qapi-types-crypto.o
+util-obj-y += qapi/qapi-types-introspect.o
+util-obj-y += qapi/qapi-types-migration.o
+util-obj-y += qapi/qapi-types-net.o
+util-obj-y += qapi/qapi-types-rocker.o
+util-obj-y += qapi/qapi-types-run-state.o
+util-obj-y += qapi/qapi-types-sockets.o
+util-obj-y += qapi/qapi-types-tpm.o
+util-obj-y += qapi/qapi-types-trace.o
+util-obj-y += qapi/qapi-types-transaction.o
+util-obj-y += qapi/qapi-types-ui.o
 util-obj-y += qapi-builtin-visit.o
-util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
+util-obj-y += qapi-visit.o
+util-obj-y += qapi/qapi-visit-block-core.o
+util-obj-y += qapi/qapi-visit-block.o
+util-obj-y += qapi/qapi-visit-char.o
+util-obj-y += qapi/qapi-visit-common.o
+util-obj-y += qapi/qapi-visit-crypto.o
+util-obj-y += qapi/qapi-visit-introspect.o
+util-obj-y += qapi/qapi-visit-migration.o
+util-obj-y += qapi/qapi-visit-net.o
+util-obj-y += qapi/qapi-visit-rocker.o
+util-obj-y += qapi/qapi-visit-run-state.o
+util-obj-y += qapi/qapi-visit-sockets.o
+util-obj-y += qapi/qapi-visit-tpm.o
+util-obj-y += qapi/qapi-visit-trace.o
+util-obj-y += qapi/qapi-visit-transaction.o
+util-obj-y += qapi/qapi-visit-ui.o
+util-obj-y += qapi-event.o
+util-obj-y += qapi/qapi-events-block-core.o
+util-obj-y += qapi/qapi-events-block.o
+util-obj-y += qapi/qapi-events-char.o
+util-obj-y += qapi/qapi-events-common.o
+util-obj-y += qapi/qapi-events-crypto.o
+util-obj-y += qapi/qapi-events-introspect.o
+util-obj-y += qapi/qapi-events-migration.o
+util-obj-y += qapi/qapi-events-net.o
+util-obj-y += qapi/qapi-events-rocker.o
+util-obj-y += qapi/qapi-events-run-state.o
+util-obj-y += qapi/qapi-events-sockets.o
+util-obj-y += qapi/qapi-events-tpm.o
+util-obj-y += qapi/qapi-events-trace.o
+util-obj-y += qapi/qapi-events-transaction.o
+util-obj-y += qapi/qapi-events-ui.o
+util-obj-y += qmp-introspect.o
 
 chardev-obj-y = chardev/
 
@@ -81,6 +129,21 @@ common-obj-$(CONFIG_FDT) += device_tree.o
 # qapi
 
 common-obj-y += qmp-commands.o
+common-obj-y += qapi/qapi-commands-block-core.o
+common-obj-y += qapi/qapi-commands-block.o
+common-obj-y += qapi/qapi-commands-char.o
+common-obj-y += qapi/qapi-commands-common.o
+common-obj-y += qapi/qapi-commands-crypto.o
+common-obj-y += qapi/qapi-commands-introspect.o
+common-obj-y += qapi/qapi-commands-migration.o
+common-obj-y += qapi/qapi-commands-net.o
+common-obj-y += qapi/qapi-commands-rocker.o
+common-obj-y += qapi/qapi-commands-run-state.o
+common-obj-y += qapi/qapi-commands-sockets.o
+common-obj-y += qapi/qapi-commands-tpm.o
+common-obj-y += qapi/qapi-commands-trace.o
+common-obj-y += qapi/qapi-commands-transaction.o
+common-obj-y += qapi/qapi-commands-ui.o
 common-obj-y += qmp-introspect.o
 common-obj-y += qmp.o hmp.o
 endif
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 46757db771..a43bccb190 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -223,14 +223,24 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
     return ret
 
 
-class QAPISchemaGenCommandVisitor(QAPISchemaMonolithicCVisitor):
+class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
 
     def __init__(self, prefix):
-        QAPISchemaMonolithicCVisitor.__init__(
-            self, prefix, 'qmp-commands',
+        QAPISchemaModularCVisitor.__init__(
+            self, prefix, 'qapi-commands',
             ' * Schema-defined QAPI/QMP commands', __doc__)
         self._regy = ''
-        self._visited_ret_types = set()
+        self._visited_ret_types = {}
+
+    # Temporary HACK:
+    def _module_basename(self, what, name):
+        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
+        if name == self._main_module:
+            return re.sub(r'qapi-commands', 'qmp-commands', basename)
+        return basename
+
+    def _begin_module(self, name):
+        self._visited_ret_types[self._genc] = set()
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -246,26 +256,29 @@ class QAPISchemaGenCommandVisitor(QAPISchemaMonolithicCVisitor):
 #include "%(prefix)sqmp-commands.h"
 
 ''',
-                             prefix=prefix))
+                             prefix=self._prefix))
         self._genh.add(mcgen('''
 #include "%(prefix)sqapi-types.h"
 #include "qapi/qmp/dispatch.h"
 
-void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-                             prefix=prefix,
-                             c_prefix=c_name(prefix, protect=False)))
+                             prefix=self._prefix))
 
     def visit_end(self):
-        self._genc.add(gen_registry(self._regy, self._prefix))
+        (genc, genh) = self._module[self._main_module]
+        genh.add(mcgen('''
+void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
+''',
+                       c_prefix=c_name(self._prefix, protect=False)))
+        genc.add(gen_registry(self._regy, self._prefix))
 
     def visit_command(self, name, info, arg_type, ret_type,
                       gen, success_response, boxed):
         if not gen:
             return
         self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
-        if ret_type and ret_type not in self._visited_ret_types:
-            self._visited_ret_types.add(ret_type)
+        if ret_type and ret_type not in self._visited_ret_types[self._genc]:
+            self._visited_ret_types[self._genc].add(ret_type)
             self._genc.add(gen_marshal_output(ret_type))
         self._genh.add(gen_marshal_decl(name))
         self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 6e5152b173..b9a52e820d 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -2073,13 +2073,20 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
         self._blurb = blurb
         self._pydoc = pydoc
         self._module = {}
+        self._main_module = None
 
     def _module_basename(self, what, name):
         if name is None:
             return re.sub(r'-', '-builtin-', what)
-        return self._prefix + what
+        basename = os.path.join(os.path.dirname(name),
+                                self._prefix + what)
+        if name == self._main_module:
+            return basename
+        return basename + '-' + os.path.splitext(os.path.basename(name))[0]
 
     def _add_module(self, name, blurb):
+        if self._main_module is None and name is not None:
+            self._main_module = name
         genc = QAPIGenC(blurb, self._pydoc)
         genh = QAPIGenH(blurb, self._pydoc)
         self._module[name] = (genc, genh)
@@ -2088,7 +2095,7 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
     def _set_module(self, name):
         self._genc, self._genh = self._module[name]
 
-    def write(self, output_dir, opt_builtins):
+    def write(self, output_dir, opt_builtins=False):
         for name in self._module:
             if name is None and not opt_builtins:
                 continue
@@ -2101,7 +2108,15 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
         pass
 
     def visit_module(self, name):
-        if len(self._module) != 1:
+        if name in self._module:
+            self._set_module(name)
             return
         self._add_module(name, self._blurb)
         self._begin_module(name)
+
+    def visit_include(self, name, info):
+        basename = self._module_basename(self._what, name)
+        self._genh.preamble_add(mcgen('''
+#include "%(basename)s.h"
+''',
+                                      basename=basename))
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 81ab3abb30..1e0b990f35 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -148,14 +148,23 @@ out:
     return ret
 
 
-class QAPISchemaGenEventVisitor(QAPISchemaMonolithicCVisitor):
+class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
 
     def __init__(self, prefix):
-        QAPISchemaMonolithicCVisitor.__init__(
-            self, prefix, 'qapi-event',
+        QAPISchemaModularCVisitor.__init__(
+            self, prefix, 'qapi-events',
             ' * Schema-defined QAPI/QMP events', __doc__)
         self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
         self._event_names = []
+
+    # Temporary HACK:
+    def _module_basename(self, what, name):
+        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
+        if name == self._main_module:
+            return re.sub(r'qapi-events', 'qapi-event', basename)
+        return basename
+
+    def _begin_module(self, name):
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -167,13 +176,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaMonolithicCVisitor):
 #include "qapi/qmp-event.h"
 
 ''',
-                             prefix=prefix))
+                             prefix=self._prefix))
         self._genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                             prefix=prefix))
+                             prefix=self._prefix))
 
     def visit_end(self):
         self._genh.add(gen_enum(self._enum_name, self._event_names))
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (21 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:13   ` Eric Blake
  2018-02-13 15:54   ` Marc-Andre Lureau
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json Markus Armbruster
                   ` (8 subsequent siblings)
  31 siblings, 2 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

In my "build everything" tree, a change to the types in
qapi-schema.json triggers a recompile of about 4800 out of 5100
objects.

The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h,
qapi-types.h.  Each of these headers still includes all its shards.
Reduce compile time by including just the shards we actually need.

To illustrate the benefits: adding a type to qapi/migration.json now
recompiles some 2300 instead of 4800 objects.  The next commit will
improve it further.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 backends/cryptodev.c             |  1 -
 backends/hostmem.c               |  3 ++-
 block.c                          |  1 -
 block/block-backend.c            |  2 +-
 block/crypto.c                   |  2 +-
 block/nbd.c                      |  2 +-
 block/nfs.c                      |  2 +-
 block/qapi.c                     |  4 ++--
 block/qcow2.c                    |  3 +--
 block/quorum.c                   |  2 +-
 block/sheepdog.c                 |  2 +-
 block/ssh.c                      |  2 +-
 block/throttle-groups.c          |  2 +-
 block/write-threshold.c          |  4 ++--
 blockdev-nbd.c                   |  2 +-
 blockdev.c                       |  5 +++--
 blockjob.c                       |  2 +-
 chardev/char-fe.c                |  1 -
 chardev/char-ringbuf.c           |  2 +-
 chardev/char-socket.c            |  1 +
 chardev/char.c                   |  3 +--
 cpus.c                           |  2 +-
 crypto/cipherpriv.h              |  2 +-
 hmp.c                            |  2 +-
 hw/acpi/core.c                   |  2 +-
 hw/block/block.c                 |  1 +
 hw/block/hd-geometry.c           |  1 +
 hw/char/virtio-console.c         |  2 +-
 hw/core/machine.c                |  2 +-
 hw/i386/pc.c                     |  2 +-
 hw/mem/nvdimm.c                  |  1 -
 hw/net/rocker/qmp-norocker.c     |  2 +-
 hw/net/rocker/rocker.c           |  2 +-
 hw/net/rocker/rocker_fp.c        |  2 +-
 hw/net/rocker/rocker_of_dpa.c    |  2 +-
 hw/net/virtio-net.c              |  2 +-
 hw/ppc/spapr_rtas.c              |  1 -
 hw/tpm/tpm_emulator.c            |  1 +
 hw/tpm/tpm_passthrough.c         |  1 +
 hw/watchdog/watchdog.c           |  2 +-
 include/block/block.h            |  2 +-
 include/block/dirty-bitmap.h     |  2 +-
 include/block/nbd.h              |  2 +-
 include/chardev/char.h           |  1 +
 include/crypto/cipher.h          |  2 +-
 include/crypto/hash.h            |  2 +-
 include/crypto/hmac.h            |  2 +-
 include/crypto/secret.h          |  1 +
 include/crypto/tlscreds.h        |  1 +
 include/hw/block/block.h         |  2 +-
 include/hw/block/fdc.h           |  2 +-
 include/hw/ppc/spapr_drc.h       |  1 +
 include/hw/qdev-properties.h     |  1 +
 include/io/dns-resolver.h        |  1 +
 include/migration/colo.h         |  2 +-
 include/migration/failover.h     |  2 +-
 include/migration/global_state.h |  1 +
 include/monitor/monitor.h        |  1 +
 include/net/filter.h             |  1 +
 include/net/net.h                |  2 +-
 include/qapi/clone-visitor.h     |  1 -
 include/qapi/error.h             |  2 +-
 include/qapi/qmp/qobject.h       |  2 +-
 include/qapi/visitor.h           |  2 +-
 include/qemu/sockets.h           |  2 +-
 include/qemu/throttle.h          |  2 +-
 include/qom/cpu.h                |  1 +
 include/qom/object.h             |  2 +-
 include/sysemu/dump.h            |  2 ++
 include/sysemu/hostmem.h         |  1 +
 include/sysemu/replay.h          |  1 +
 include/sysemu/sysemu.h          |  1 +
 include/sysemu/tpm.h             |  1 +
 include/sysemu/watchdog.h        |  2 +-
 include/ui/input.h               |  2 +-
 io/channel-socket.c              |  1 +
 io/dns-resolver.c                |  1 +
 migration/colo-failover.c        |  2 +-
 migration/colo.c                 |  2 +-
 migration/migration.c            |  4 ++--
 migration/migration.h            |  1 +
 migration/ram.c                  |  2 +-
 migration/ram.h                  |  2 +-
 net/colo-compare.c               |  1 -
 net/filter-buffer.c              |  2 +-
 net/filter-mirror.c              |  1 -
 net/filter-rewriter.c            |  1 -
 net/net.c                        |  4 ++--
 net/tap_int.h                    |  2 +-
 net/vhost-user.c                 |  2 +-
 qemu-img.c                       |  2 +-
 qom/object.c                     |  2 +-
 qom/object_interfaces.c          |  1 -
 replay/replay-input.c            |  1 +
 replication.h                    |  1 +
 scripts/qapi/commands.py         | 14 ++++++++------
 scripts/qapi/events.py           | 10 ++++++----
 scripts/qapi/types.py            |  8 +++++---
 scripts/qapi/visit.py            | 10 ++++++----
 stubs/tpm.c                      |  3 ++-
 target/s390x/kvm.c               |  1 -
 tests/test-char.c                |  2 +-
 tests/test-qmp-event.c           |  1 -
 tpm.c                            |  2 +-
 trace/qmp.c                      |  2 +-
 ui/console.c                     |  2 +-
 ui/input-legacy.c                |  2 +-
 ui/input.c                       |  2 +-
 ui/spice-core.c                  |  4 ++--
 ui/vnc.c                         |  2 +-
 ui/vnc.h                         |  1 +
 util/qemu-sockets.c              |  2 +-
 vl.c                             |  4 ++--
 113 files changed, 133 insertions(+), 109 deletions(-)

diff --git a/backends/cryptodev.c b/backends/cryptodev.c
index d0dff1a463..f35be377ef 100644
--- a/backends/cryptodev.c
+++ b/backends/cryptodev.c
@@ -26,7 +26,6 @@
 #include "hw/boards.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 #include "qemu/config-file.h"
 #include "qom/object_interfaces.h"
 #include "hw/virtio/virtio-crypto.h"
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 81d14554a7..0afaf7160a 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -9,12 +9,13 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+
 #include "qemu/osdep.h"
 #include "sysemu/hostmem.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
+#include "qapi-builtin-visit.h"
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 #include "qemu/config-file.h"
 #include "qom/object_interfaces.h"
 
diff --git a/block.c b/block.c
index 05a484b4b8..0b2784f322 100644
--- a/block.c
+++ b/block.c
@@ -41,7 +41,6 @@
 #include "qemu/coroutine.h"
 #include "block/qapi.h"
 #include "qemu/timer.h"
-#include "qapi-event.h"
 #include "qemu/cutils.h"
 #include "qemu/id.h"
 
diff --git a/block/block-backend.c b/block/block-backend.c
index 0266ac990b..94ffbb6a60 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -17,8 +17,8 @@
 #include "block/throttle-groups.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
-#include "qapi-event.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-block.h"
 #include "qemu/id.h"
 #include "qemu/option.h"
 #include "trace.h"
diff --git a/block/crypto.c b/block/crypto.c
index 70e3691cd8..c87abd5250 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -24,9 +24,9 @@
 #include "sysemu/block-backend.h"
 #include "crypto/block.h"
 #include "qapi/opts-visitor.h"
+#include "qapi/qapi-visit-crypto.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qobject-input-visitor.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
 #include "qemu/option.h"
 #include "block/crypto.h"
diff --git a/block/nbd.c b/block/nbd.c
index 411eeb42a7..6c0e766b6f 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -33,7 +33,7 @@
 #include "block/block_int.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp/qdict.h"
diff --git a/block/nfs.c b/block/nfs.c
index 6576a73d6e..bbdb4fadad 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -35,9 +35,9 @@
 #include "qemu/uri.h"
 #include "qemu/cutils.h"
 #include "sysemu/sysemu.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
-#include "qapi-visit.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
 #include <nfsc/libnfs.h>
diff --git a/block/qapi.c b/block/qapi.c
index 1fdeb1ef2f..4c9923d262 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -27,10 +27,10 @@
 #include "block/block_int.h"
 #include "block/throttle-groups.h"
 #include "block/write-threshold.h"
-#include "qmp-commands.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
 #include "qapi/qobject-output-visitor.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qlist.h"
diff --git a/block/qcow2.c b/block/qcow2.c
index 9245deac19..2fc58415bb 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -30,15 +30,14 @@
 #include "block/qcow2.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-block-core.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
-#include "qapi-event.h"
 #include "trace.h"
 #include "qemu/option_int.h"
 #include "qemu/cutils.h"
 #include "qemu/bswap.h"
 #include "qapi/opts-visitor.h"
-#include "qapi-visit.h"
 #include "block/crypto.h"
 
 /*
diff --git a/block/quorum.c b/block/quorum.c
index 19f1c34425..14333c18aa 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -18,11 +18,11 @@
 #include "qemu/option.h"
 #include "block/block_int.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-block.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
-#include "qapi-event.h"
 #include "crypto/hash.h"
 
 #define HASH_LENGTH 32
diff --git a/block/sheepdog.c b/block/sheepdog.c
index af125a2c8d..4c20fcda04 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -13,8 +13,8 @@
  */
 
 #include "qemu/osdep.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qemu/uri.h"
diff --git a/block/ssh.c b/block/ssh.c
index b63addcf94..b11d4c5e86 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -34,7 +34,7 @@
 #include "qemu/cutils.h"
 #include "qemu/sockets.h"
 #include "qemu/uri.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qobject-input-visitor.h"
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
index f26bcb5eee..36cc0430c3 100644
--- a/block/throttle-groups.c
+++ b/block/throttle-groups.c
@@ -30,7 +30,7 @@
 #include "qemu/thread.h"
 #include "sysemu/qtest.h"
 #include "qapi/error.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qom/object.h"
 #include "qom/object_interfaces.h"
 
diff --git a/block/write-threshold.c b/block/write-threshold.c
index db3de0fa6d..1d48fc2077 100644
--- a/block/write-threshold.c
+++ b/block/write-threshold.c
@@ -15,9 +15,9 @@
 #include "qemu/coroutine.h"
 #include "block/write-threshold.h"
 #include "qemu/notify.h"
-#include "qapi-event.h"
 #include "qapi/error.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-events-block-core.h"
 
 uint64_t bdrv_write_threshold_get(const BlockDriverState *bs)
 {
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 3a5479bdad..65a84739ed 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -14,8 +14,8 @@
 #include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block.h"
 #include "sysemu/sysemu.h"
-#include "qmp-commands.h"
 #include "block/nbd.h"
 #include "io/channel-socket.h"
 #include "io/net-listener.h"
diff --git a/blockdev.c b/blockdev.c
index bdbdeae7e4..85e011191b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -40,10 +40,12 @@
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/qapi-commands-transaction.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qstring.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qlist.h"
@@ -51,7 +53,6 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/iothread.h"
 #include "block/block_int.h"
-#include "qmp-commands.h"
 #include "block/trace.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/qtest.h"
diff --git a/blockjob.c b/blockjob.c
index 3f52f29f75..801d29d849 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -30,11 +30,11 @@
 #include "block/block_int.h"
 #include "sysemu/block-backend.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-block-core.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/coroutine.h"
 #include "qemu/id.h"
 #include "qemu/timer.h"
-#include "qapi-event.h"
 
 /* Right now, this mutex is only needed to synchronize accesses to job->busy
  * and job->sleep_timer, such as concurrent calls to block_job_do_yield and
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index e5f870e4d2..392db78b13 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -25,7 +25,6 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
-#include "qapi-visit.h"
 #include "sysemu/replay.h"
 
 #include "chardev/char-fe.h"
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
index 679afaa4fd..87832e2792 100644
--- a/chardev/char-ringbuf.c
+++ b/chardev/char-ringbuf.c
@@ -24,8 +24,8 @@
 
 #include "qemu/osdep.h"
 #include "chardev/char.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-char.h"
 #include "qemu/base64.h"
 #include "qemu/option.h"
 
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index bdd6cff5f6..22f65971a1 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -31,6 +31,7 @@
 #include "qemu/option.h"
 #include "qapi/error.h"
 #include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-sockets.h"
 
 #include "chardev/char-io.h"
 
diff --git a/chardev/char.c b/chardev/char.c
index c9a4da5516..5d7b079ef0 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -29,9 +29,8 @@
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "chardev/char.h"
-#include "qmp-commands.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-char.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/replay.h"
 #include "qemu/help_option.h"
diff --git a/cpus.c b/cpus.c
index f298b659f4..ddb7f9b811 100644
--- a/cpus.c
+++ b/cpus.c
@@ -27,6 +27,7 @@
 #include "cpu.h"
 #include "monitor/monitor.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-run-state.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
@@ -49,7 +50,6 @@
 #include "qemu/bitmap.h"
 #include "qemu/seqlock.h"
 #include "tcg.h"
-#include "qapi-event.h"
 #include "hw/nmi.h"
 #include "sysemu/replay.h"
 #include "hw/boards.h"
diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h
index 77da4c2f32..0823239f41 100644
--- a/crypto/cipherpriv.h
+++ b/crypto/cipherpriv.h
@@ -15,7 +15,7 @@
 #ifndef QCRYPTO_CIPHERPRIV_H
 #define QCRYPTO_CIPHERPRIV_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-crypto.h"
 
 typedef struct QCryptoCipherDriver QCryptoCipherDriver;
 
diff --git a/hmp.c b/hmp.c
index 7870d6a300..a49f4c126e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -29,11 +29,11 @@
 #include "monitor/qdev.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
+#include "qapi-builtin-visit.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/string-output-visitor.h"
-#include "qapi-visit.h"
 #include "qom/object_interfaces.h"
 #include "ui/console.h"
 #include "block/nbd.h"
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index b50b3ca772..5d4ce925dc 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -27,8 +27,8 @@
 #include "qemu/config-file.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
+#include "qapi/qapi-events-run-state.h"
 #include "qapi-visit.h"
-#include "qapi-event.h"
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 
diff --git a/hw/block/block.c b/hw/block/block.c
index b0269c857f..b91e2b6d7e 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -12,6 +12,7 @@
 #include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "qapi/error.h"
+#include "qapi/qapi-types-block.h"
 #include "qemu/error-report.h"
 
 void blkconf_serial(BlockConf *conf, char **serial)
diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
index 57ad5012a7..79384a2b0a 100644
--- a/hw/block/hd-geometry.c
+++ b/hw/block/hd-geometry.c
@@ -32,6 +32,7 @@
 
 #include "qemu/osdep.h"
 #include "sysemu/block-backend.h"
+#include "qapi/qapi-types-block.h"
 #include "qemu/bswap.h"
 #include "hw/block/block.h"
 #include "trace.h"
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 4be5d4ee52..679a824888 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -15,8 +15,8 @@
 #include "qemu/error-report.h"
 #include "trace.h"
 #include "hw/virtio/virtio-serial.h"
-#include "qapi-event.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-char.h"
 
 #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
 #define VIRTIO_CONSOLE(obj) \
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cdc1163dc6..f35075bff6 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -13,7 +13,7 @@
 #include "qemu/osdep.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-common.h"
 #include "qapi/visitor.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 55e69d66fe..94cfd40ef2 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -67,8 +67,8 @@
 #include "acpi-build.h"
 #include "hw/mem/pc-dimm.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-common.h"
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 #include "qom/cpu.h"
 #include "hw/nmi.h"
 #include "hw/i386/intel_iommu.h"
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 61e677f92f..acb656b672 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -25,7 +25,6 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 #include "hw/mem/nvdimm.h"
 
 static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name,
diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c
index 94c1e480ae..0d60513c01 100644
--- a/hw/net/rocker/qmp-norocker.c
+++ b/hw/net/rocker/qmp-norocker.c
@@ -17,8 +17,8 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-rocker.h"
 #include "qapi/qmp/qerror.h"
 
 RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index a2a76c2a74..c02cbefece 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -22,9 +22,9 @@
 #include "net/net.h"
 #include "net/eth.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-rocker.h"
 #include "qemu/iov.h"
 #include "qemu/bitops.h"
-#include "qmp-commands.h"
 
 #include "rocker.h"
 #include "rocker_hw.h"
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 4b3c9847db..27b17c890f 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -16,7 +16,7 @@
 
 #include "qemu/osdep.h"
 #include "net/clients.h"
-
+#include "qapi/qapi-types-rocker.h"
 #include "rocker.h"
 #include "rocker_hw.h"
 #include "rocker_fp.h"
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 9339df2d09..60046720a5 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -17,9 +17,9 @@
 #include "qemu/osdep.h"
 #include "net/eth.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-rocker.h"
 #include "qemu/iov.h"
 #include "qemu/timer.h"
-#include "qmp-commands.h"
 
 #include "rocker.h"
 #include "rocker_hw.h"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 369d40b378..188744e17d 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -23,7 +23,7 @@
 #include "net/vhost_net.h"
 #include "hw/virtio/virtio-bus.h"
 #include "qapi/error.h"
-#include "qapi-event.h"
+#include "qapi/qapi-events-net.h"
 #include "hw/virtio/virtio-access.h"
 #include "migration/misc.h"
 
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 4bb939d3d1..0ec5fa4cfe 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -38,7 +38,6 @@
 #include "hw/ppc/spapr_vio.h"
 #include "hw/ppc/spapr_rtas.h"
 #include "hw/ppc/ppc.h"
-#include "qapi-event.h"
 #include "hw/boards.h"
 
 #include <libfdt.h>
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index b787aee13b..f187a72c10 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -38,6 +38,7 @@
 #include "migration/blocker.h"
 #include "qapi/error.h"
 #include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-tpm.h"
 #include "chardev/char-fe.h"
 
 #define DEBUG_TPM 0
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index a495fe07f4..211df3191c 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -30,6 +30,7 @@
 #include "tpm_int.h"
 #include "hw/hw.h"
 #include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-tpm.h"
 #include "tpm_util.h"
 
 #define DEBUG_TPM 0
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 98a5dd6689..c7843d5748 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -24,9 +24,9 @@
 #include "qemu/config-file.h"
 #include "qemu/queue.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-run-state.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/watchdog.h"
-#include "qapi-event.h"
 #include "hw/nmi.h"
 #include "qemu/help_option.h"
 #include "qmp-commands.h"
diff --git a/include/block/block.h b/include/block/block.h
index 24ef816960..a1936996db 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -2,7 +2,7 @@
 #define BLOCK_H
 
 #include "block/aio.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-block-core.h"
 #include "qemu/iov.h"
 #include "qemu/coroutine.h"
 #include "block/accounting.h"
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 3da8486ab1..1454be358d 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -2,7 +2,7 @@
 #define BLOCK_DIRTY_BITMAP_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-block-core.h"
 #include "qemu/hbitmap.h"
 
 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
diff --git a/include/block/nbd.h b/include/block/nbd.h
index fc50003003..631290dac9 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -20,7 +20,7 @@
 #ifndef NBD_H
 #define NBD_H
 
-
+#include "qapi/qapi-types-block.h"
 #include "io/channel-socket.h"
 #include "crypto/tlscreds.h"
 
diff --git a/include/chardev/char.h b/include/chardev/char.h
index a381dc3df8..ebf1e0ba04 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_CHAR_H
 #define QEMU_CHAR_H
 
+#include "qapi/qapi-types-char.h"
 #include "qemu/main-loop.h"
 #include "qemu/bitmap.h"
 #include "qom/object.h"
diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h
index 984fb8243f..bce2d4c8e4 100644
--- a/include/crypto/cipher.h
+++ b/include/crypto/cipher.h
@@ -21,7 +21,7 @@
 #ifndef QCRYPTO_CIPHER_H
 #define QCRYPTO_CIPHER_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-crypto.h"
 
 typedef struct QCryptoCipher QCryptoCipher;
 
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index ca3267f3df..077ac7bea0 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -21,7 +21,7 @@
 #ifndef QCRYPTO_HASH_H
 #define QCRYPTO_HASH_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-crypto.h"
 
 /* See also "QCryptoHashAlgorithm" defined in qapi/crypto.json */
 
diff --git a/include/crypto/hmac.h b/include/crypto/hmac.h
index 5e88905989..aa3c97a2ff 100644
--- a/include/crypto/hmac.h
+++ b/include/crypto/hmac.h
@@ -12,7 +12,7 @@
 #ifndef QCRYPTO_HMAC_H
 #define QCRYPTO_HMAC_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-crypto.h"
 
 typedef struct QCryptoHmac QCryptoHmac;
 struct QCryptoHmac {
diff --git a/include/crypto/secret.h b/include/crypto/secret.h
index 07a963e794..edd0e13236 100644
--- a/include/crypto/secret.h
+++ b/include/crypto/secret.h
@@ -21,6 +21,7 @@
 #ifndef QCRYPTO_SECRET_H
 #define QCRYPTO_SECRET_H
 
+#include "qapi/qapi-types-crypto.h"
 #include "qom/object.h"
 
 #define TYPE_QCRYPTO_SECRET "secret"
diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
index ad47d88be7..6b011e1dbc 100644
--- a/include/crypto/tlscreds.h
+++ b/include/crypto/tlscreds.h
@@ -21,6 +21,7 @@
 #ifndef QCRYPTO_TLSCREDS_H
 #define QCRYPTO_TLSCREDS_H
 
+#include "qapi/qapi-types-crypto.h"
 #include "qom/object.h"
 
 #ifdef CONFIG_GNUTLS
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
index f532d10e35..d4f4dfffab 100644
--- a/include/hw/block/block.h
+++ b/include/hw/block/block.h
@@ -12,7 +12,7 @@
 #define HW_BLOCK_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-block-core.h"
 
 /* Configuration */
 
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
index 68a0c904ea..3b813c7f7d 100644
--- a/include/hw/block/fdc.h
+++ b/include/hw/block/fdc.h
@@ -2,7 +2,7 @@
 #define HW_FDC_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-block.h"
 
 /* fdc.c */
 #define MAX_FD 2
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index f8d9f5b231..f6ff32e7e2 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -14,6 +14,7 @@
 #define HW_SPAPR_DRC_H
 
 #include <libfdt.h>
+#include "qapi/qapi-types-run-state.h"
 #include "qom/object.h"
 #include "sysemu/sysemu.h"
 #include "hw/qdev.h"
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 1d61a35108..40c2c8acb1 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_QDEV_PROPERTIES_H
 #define QEMU_QDEV_PROPERTIES_H
 
+#include "qapi-types.h"
 #include "hw/qdev-core.h"
 
 /*** qdev-properties.c ***/
diff --git a/include/io/dns-resolver.h b/include/io/dns-resolver.h
index 2f69c08c13..1a162185cc 100644
--- a/include/io/dns-resolver.h
+++ b/include/io/dns-resolver.h
@@ -22,6 +22,7 @@
 #define QIO_DNS_RESOLVER_H
 
 #include "qemu-common.h"
+#include "qapi/qapi-types-sockets.h"
 #include "qom/object.h"
 #include "io/task.h"
 
diff --git a/include/migration/colo.h b/include/migration/colo.h
index 50ace16205..2fe48ad353 100644
--- a/include/migration/colo.h
+++ b/include/migration/colo.h
@@ -14,7 +14,7 @@
 #define QEMU_COLO_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-migration.h"
 
 void colo_info_init(void);
 
diff --git a/include/migration/failover.h b/include/migration/failover.h
index ad91ef2381..4c37218dcc 100644
--- a/include/migration/failover.h
+++ b/include/migration/failover.h
@@ -14,7 +14,7 @@
 #define QEMU_FAILOVER_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-migration.h"
 
 void failover_init_state(void);
 FailoverStatus failover_set_state(FailoverStatus old_state,
diff --git a/include/migration/global_state.h b/include/migration/global_state.h
index d307de8350..fd22dd3034 100644
--- a/include/migration/global_state.h
+++ b/include/migration/global_state.h
@@ -13,6 +13,7 @@
 #ifndef QEMU_MIGRATION_GLOBAL_STATE_H
 #define QEMU_MIGRATION_GLOBAL_STATE_H
 
+#include "qapi/qapi-types-run-state.h"
 #include "sysemu/sysemu.h"
 
 void register_global_state(void);
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index ad64ad8e68..50f7cea057 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -3,6 +3,7 @@
 
 #include "qemu-common.h"
 #include "block/block.h"
+#include "qapi-types.h"
 #include "qemu/readline.h"
 
 extern Monitor *cur_mon;
diff --git a/include/net/filter.h b/include/net/filter.h
index 0c4a2ea6c9..435acd6f82 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -9,6 +9,7 @@
 #ifndef QEMU_NET_FILTER_H
 #define QEMU_NET_FILTER_H
 
+#include "qapi/qapi-types-net.h"
 #include "qom/object.h"
 #include "qemu-common.h"
 #include "net/queue.h"
diff --git a/include/net/net.h b/include/net/net.h
index 3fc48e4f51..727643032c 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -2,7 +2,7 @@
 #define QEMU_NET_H
 
 #include "qemu/queue.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-net.h"
 #include "net/queue.h"
 #include "migration/vmstate.h"
 
diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h
index b119d3daa9..5b665ee38c 100644
--- a/include/qapi/clone-visitor.h
+++ b/include/qapi/clone-visitor.h
@@ -12,7 +12,6 @@
 #define QAPI_CLONE_VISITOR_H
 
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 
 /*
  * The clone visitor is for direct use only by the QAPI_CLONE() macro;
diff --git a/include/qapi/error.h b/include/qapi/error.h
index c2115a6a4a..bcb86a79f5 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -115,7 +115,7 @@
 #ifndef ERROR_H
 #define ERROR_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-common.h"
 
 /*
  * Overall category of an error.
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index 38ac68845c..a2964fbf25 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -32,7 +32,7 @@
 #ifndef QOBJECT_H
 #define QOBJECT_H
 
-#include "qapi-types.h"
+#include "qapi-builtin-types.h"
 
 struct QObject {
     QType type;
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index ecff296c11..9e57508446 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -15,7 +15,7 @@
 #ifndef QAPI_VISITOR_H
 #define QAPI_VISITOR_H
 
-#include "qapi-types.h"
+#include "qapi-builtin-types.h"
 
 /*
  * The QAPI schema defines both a set of C data types, and a QMP wire
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 8889bcb1ec..e88d4c37ab 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -9,7 +9,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 
 #endif /* !_WIN32 */
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-sockets.h"
 
 /* misc helpers */
 int qemu_socket(int domain, int type, int protocol);
diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
index 03d45f44f8..abeb886d93 100644
--- a/include/qemu/throttle.h
+++ b/include/qemu/throttle.h
@@ -26,7 +26,7 @@
 #define THROTTLE_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-block-core.h"
 #include "qemu/timer.h"
 
 #define THROTTLE_VALUE_MAX 1000000000000000LL
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index aff88fa16f..dc6d4956a8 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,7 @@
 #include "disas/bfd.h"
 #include "exec/hwaddr.h"
 #include "exec/memattrs.h"
+#include "qapi/qapi-types-run-state.h"
 #include "qemu/bitmap.h"
 #include "qemu/queue.h"
 #include "qemu/thread.h"
diff --git a/include/qom/object.h b/include/qom/object.h
index dc73d59660..5b5c016d8f 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -14,7 +14,7 @@
 #ifndef QEMU_OBJECT_H
 #define QEMU_OBJECT_H
 
-#include "qapi-types.h"
+#include "qapi-builtin-types.h"
 #include "qemu/queue.h"
 
 struct TypeImpl;
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index c14bcfe8c6..2424e31425 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -14,6 +14,8 @@
 #ifndef DUMP_H
 #define DUMP_H
 
+#include "qapi-types.h"
+
 #define MAKEDUMPFILE_SIGNATURE      "makedumpfile"
 #define MAX_SIZE_MDF_HEADER         (4096) /* max size of makedumpfile_header */
 #define TYPE_FLAT_HEADER            (1)    /* type of flattened format */
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index 621a3f9d42..6424f96df9 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -14,6 +14,7 @@
 #define SYSEMU_HOSTMEM_H
 
 #include "sysemu/sysemu.h" /* for MAX_NODES */
+#include "qapi-types.h"
 #include "qom/object.h"
 #include "exec/memory.h"
 #include "qemu/bitmap.h"
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index dc8ae7b6b1..fb533ed9b6 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -13,6 +13,7 @@
  */
 
 #include "sysemu.h"
+#include "qapi-types.h"
 
 /* replay clock kinds */
 enum ReplayClockKind {
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 77bb3da582..bfbef9e69c 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -2,6 +2,7 @@
 #define SYSEMU_H
 /* Misc. things related to the system emulator.  */
 
+#include "qapi/qapi-types-run-state.h"
 #include "qemu/queue.h"
 #include "qemu/timer.h"
 #include "qemu/notify.h"
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 32b753d4f3..9ae1ab6da3 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -12,6 +12,7 @@
 #ifndef QEMU_TPM_H
 #define QEMU_TPM_H
 
+#include "qapi/qapi-types-tpm.h"
 #include "qom/object.h"
 
 int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
diff --git a/include/sysemu/watchdog.h b/include/sysemu/watchdog.h
index 677ace3945..a08d16380d 100644
--- a/include/sysemu/watchdog.h
+++ b/include/sysemu/watchdog.h
@@ -23,7 +23,7 @@
 #define QEMU_WATCHDOG_H
 
 #include "qemu/queue.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-run-state.h"
 
 struct WatchdogTimerModel {
     QLIST_ENTRY(WatchdogTimerModel) entry;
diff --git a/include/ui/input.h b/include/ui/input.h
index ceb22b8eef..16395ab8f2 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -1,7 +1,7 @@
 #ifndef INPUT_H
 #define INPUT_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-ui.h"
 
 #define INPUT_EVENT_MASK_KEY   (1<<INPUT_EVENT_KIND_KEY)
 #define INPUT_EVENT_MASK_BTN   (1<<INPUT_EVENT_KIND_BTN)
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 563e297357..8359b6683a 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "io/channel-socket.h"
 #include "io/channel-watch.h"
 #include "trace.h"
diff --git a/io/dns-resolver.c b/io/dns-resolver.c
index c072d121c3..8c924071c4 100644
--- a/io/dns-resolver.c
+++ b/io/dns-resolver.c
@@ -21,6 +21,7 @@
 #include "qemu/osdep.h"
 #include "io/dns-resolver.h"
 #include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "qemu/sockets.h"
 #include "qapi/error.h"
 #include "qemu/cutils.h"
diff --git a/migration/colo-failover.c b/migration/colo-failover.c
index 891785cb63..0ae0c41221 100644
--- a/migration/colo-failover.c
+++ b/migration/colo-failover.c
@@ -15,8 +15,8 @@
 #include "migration/failover.h"
 #include "qemu/main-loop.h"
 #include "migration.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-migration.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
 #include "trace.h"
diff --git a/migration/colo.c b/migration/colo.c
index 245a46d59d..4381067ed4 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -13,6 +13,7 @@
 #include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-migration.h"
 #include "qemu-file-channel.h"
 #include "migration.h"
 #include "qemu-file.h"
@@ -24,7 +25,6 @@
 #include "qemu/error-report.h"
 #include "migration/failover.h"
 #include "replication.h"
-#include "qmp-commands.h"
 
 static bool vmstate_loading;
 
diff --git a/migration/migration.c b/migration/migration.c
index 86d69120a6..d26c5999de 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -31,15 +31,15 @@
 #include "migration/vmstate.h"
 #include "block/block.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-events-migration.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qnull.h"
 #include "qemu/rcu.h"
 #include "block.h"
 #include "postcopy-ram.h"
 #include "qemu/thread.h"
-#include "qmp-commands.h"
 #include "trace.h"
-#include "qapi-event.h"
 #include "exec/target_page.h"
 #include "io/channel-buffer.h"
 #include "migration/colo.h"
diff --git a/migration/migration.h b/migration/migration.h
index 848f638a20..e2f18256c9 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -15,6 +15,7 @@
 #define QEMU_MIGRATION_H
 
 #include "qemu-common.h"
+#include "qapi/qapi-types-migration.h"
 #include "qemu/thread.h"
 #include "exec/cpu-common.h"
 #include "qemu/coroutine_int.h"
diff --git a/migration/ram.c b/migration/ram.c
index 8333d8e35e..1b30305faf 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -29,7 +29,6 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include <zlib.h>
-#include "qapi-event.h"
 #include "qemu/cutils.h"
 #include "qemu/bitops.h"
 #include "qemu/bitmap.h"
@@ -44,6 +43,7 @@
 #include "migration/page_cache.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-migration.h"
 #include "qapi/qmp/qerror.h"
 #include "trace.h"
 #include "exec/ram_addr.h"
diff --git a/migration/ram.h b/migration/ram.h
index f3a227b4fc..53f0021c51 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -30,7 +30,7 @@
 #define QEMU_MIGRATION_RAM_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-migration.h"
 #include "exec/cpu-common.h"
 
 extern MigrationStats ram_counters;
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 76e03fdb14..23b2d2c4cc 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -25,7 +25,6 @@
 #include "net/queue.h"
 #include "chardev/char-fe.h"
 #include "qemu/sockets.h"
-#include "qapi-visit.h"
 #include "net/colo.h"
 #include "sysemu/iothread.h"
 
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 9ce96aaa35..7c487629f9 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -13,8 +13,8 @@
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "qemu/iov.h"
+#include "qapi-builtin-visit.h"
 #include "qapi/qmp/qerror.h"
-#include "qapi-visit.h"
 #include "qom/object.h"
 
 #define TYPE_FILTER_BUFFER "filter-buffer"
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index bd78e25d12..3a61cf21e8 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -14,7 +14,6 @@
 #include "net/net.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
-#include "qapi-visit.h"
 #include "qom/object.h"
 #include "qemu/main-loop.h"
 #include "qemu/error-report.h"
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index 6201494ceb..62dad2d773 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -16,7 +16,6 @@
 #include "net/net.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
-#include "qapi-visit.h"
 #include "qom/object.h"
 #include "qemu/main-loop.h"
 #include "qemu/iov.h"
diff --git a/net/net.c b/net/net.c
index 7d42925258..547c499110 100644
--- a/net/net.c
+++ b/net/net.c
@@ -33,18 +33,18 @@
 
 #include "monitor/monitor.h"
 #include "qemu/help_option.h"
+#include "qapi/qapi-commands-net.h"
+#include "qapi/qapi-visit-net.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "qemu/cutils.h"
 #include "qemu/config-file.h"
-#include "qmp-commands.h"
 #include "hw/qdev.h"
 #include "qemu/iov.h"
 #include "qemu/main-loop.h"
 #include "qemu/option.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
 #include "sysemu/sysemu.h"
diff --git a/net/tap_int.h b/net/tap_int.h
index ae6888f74a..9f931d52d6 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -27,7 +27,7 @@
 #define NET_TAP_INT_H
 
 #include "qemu-common.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-net.h"
 
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
              int vnet_hdr_required, int mq_required, Error **errp);
diff --git a/net/vhost-user.c b/net/vhost-user.c
index cb45512506..98f3601049 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -14,10 +14,10 @@
 #include "net/vhost-user.h"
 #include "chardev/char-fe.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-net.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "qemu/option.h"
-#include "qmp-commands.h"
 #include "trace.h"
 
 typedef struct VhostUserState {
diff --git a/qemu-img.c b/qemu-img.c
index 56edc15218..40bf7aa7d1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -27,7 +27,7 @@
 
 #include "qemu-version.h"
 #include "qapi/error.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qdict.h"
diff --git a/qom/object.c b/qom/object.c
index 5dcee4683c..81b4f7ac48 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -16,9 +16,9 @@
 #include "qom/object_interfaces.h"
 #include "qemu/cutils.h"
 #include "qapi/visitor.h"
-#include "qapi-visit.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/string-output-visitor.h"
+#include "qapi-builtin-visit.h"
 #include "qapi/qmp/qerror.h"
 #include "trace.h"
 
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 43d9aa0946..2f76e1f36d 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -5,7 +5,6 @@
 #include "qom/object_interfaces.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
-#include "qapi-visit.h"
 #include "qapi/opts-visitor.h"
 #include "qemu/config-file.h"
 
diff --git a/replay/replay-input.c b/replay/replay-input.c
index 3ab1536bf7..6ee8b5f8db 100644
--- a/replay/replay-input.c
+++ b/replay/replay-input.c
@@ -16,6 +16,7 @@
 #include "qemu/notify.h"
 #include "ui/input.h"
 #include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-ui.h"
 
 void replay_save_input_event(InputEvent *evt)
 {
diff --git a/replication.h b/replication.h
index ece6ca6133..8faefe005f 100644
--- a/replication.h
+++ b/replication.h
@@ -15,6 +15,7 @@
 #ifndef REPLICATION_H
 #define REPLICATION_H
 
+#include "qapi/qapi-types-block-core.h"
 #include "qemu/queue.h"
 
 typedef struct ReplicationOps ReplicationOps;
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index a43bccb190..953449171b 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -241,6 +241,9 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
 
     def _begin_module(self, name):
         self._visited_ret_types[self._genc] = set()
+        commands = self._module_basename('qapi-commands', name)
+        types = self._module_basename('qapi-types', name)
+        visit = self._module_basename('qapi-visit', name)
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
@@ -251,18 +254,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/dealloc-visitor.h"
 #include "qapi/error.h"
-#include "%(prefix)sqapi-types.h"
-#include "%(prefix)sqapi-visit.h"
-#include "%(prefix)sqmp-commands.h"
+#include "%(visit)s.h"
+#include "%(commands)s.h"
 
 ''',
-                             prefix=self._prefix))
+                             commands=commands, visit=visit))
         self._genh.add(mcgen('''
-#include "%(prefix)sqapi-types.h"
+#include "%(types)s.h"
 #include "qapi/qmp/dispatch.h"
 
 ''',
-                             prefix=self._prefix))
+                             types=types))
 
     def visit_end(self):
         (genc, genh) = self._module[self._main_module]
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 1e0b990f35..5ad6708491 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -165,24 +165,26 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         return basename
 
     def _begin_module(self, name):
+        types = self._module_basename('qapi-types', name)
+        visit = self._module_basename('qapi-visit', name)
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "%(prefix)sqapi-event.h"
-#include "%(prefix)sqapi-visit.h"
+#include "%(visit)s.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/qmp-event.h"
 
 ''',
-                             prefix=self._prefix))
+                             visit=visit, prefix=self._prefix))
         self._genh.add(mcgen('''
 #include "qapi/util.h"
-#include "%(prefix)sqapi-types.h"
+#include "%(types)s.h"
 
 ''',
-                             prefix=self._prefix))
+                             types=types))
 
     def visit_end(self):
         self._genh.add(gen_enum(self._enum_name, self._event_names))
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 59826b1162..2a3c502cf6 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -185,13 +185,15 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
 '''))
 
     def _begin_module(self, name):
+        types = self._module_basename('qapi-types', name)
+        visit = self._module_basename('qapi-visit', name)
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
-#include "%(prefix)sqapi-types.h"
-#include "%(prefix)sqapi-visit.h"
+#include "%(types)s.h"
+#include "%(visit)s.h"
 ''',
-                                      prefix=self._prefix))
+                                      types=types, visit=visit))
         self._genh.preamble_add(mcgen('''
 #include "qapi-builtin-types.h"
 '''))
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 9b678e7263..de09966643 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -284,20 +284,22 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
                                       prefix=prefix))
 
     def _begin_module(self, name):
+        types = self._module_basename('qapi-types', name)
+        visit = self._module_basename('qapi-visit', name)
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
-#include "%(prefix)sqapi-visit.h"
+#include "%(visit)s.h"
 ''',
-                                      prefix=self._prefix))
+                                      visit=visit, prefix=self._prefix))
         self._genh.preamble_add(mcgen('''
 #include "qapi-builtin-visit.h"
-#include "%(prefix)sqapi-types.h"
+#include "%(types)s.h"
 
 ''',
-                                      prefix=self._prefix))
+                                      types=types))
 
     def visit_enum_type(self, name, info, values, prefix):
         self._genh.add(gen_visit_decl(name, scalar=True))
diff --git a/stubs/tpm.c b/stubs/tpm.c
index c18aac1c73..6729bc8517 100644
--- a/stubs/tpm.c
+++ b/stubs/tpm.c
@@ -4,9 +4,10 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  */
+
 #include "qemu/osdep.h"
+#include "qapi/qapi-commands-tpm.h"
 #include "sysemu/tpm.h"
-#include "qmp-commands.h"
 
 int tpm_init(void)
 {
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 0301e9d519..00db81f438 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -41,7 +41,6 @@
 #include "exec/gdbstub.h"
 #include "exec/address-spaces.h"
 #include "trace.h"
-#include "qapi-event.h"
 #include "hw/s390x/s390-pci-inst.h"
 #include "hw/s390x/s390-pci-bus.h"
 #include "hw/s390x/ipl.h"
diff --git a/tests/test-char.c b/tests/test-char.c
index b358620911..b3a77af085 100644
--- a/tests/test-char.c
+++ b/tests/test-char.c
@@ -8,9 +8,9 @@
 #include "chardev/char-mux.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-char.h"
 #include "qapi/qmp/qdict.h"
 #include "qom/qom-qobject.h"
-#include "qmp-commands.h"
 
 static bool quit;
 
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 8012341343..5fbe7e551f 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -14,7 +14,6 @@
 #include "qemu/osdep.h"
 
 #include "qemu-common.h"
-#include "test-qapi-visit.h"
 #include "test-qapi-event.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qbool.h"
diff --git a/tpm.c b/tpm.c
index d11b10bed8..2db03a09b2 100644
--- a/tpm.c
+++ b/tpm.c
@@ -15,12 +15,12 @@
 #include "qemu/osdep.h"
 
 #include "qapi/error.h"
+#include "qapi/qapi-commands-tpm.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/tpm_backend.h"
 #include "sysemu/tpm.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
-#include "qmp-commands.h"
 
 static QLIST_HEAD(, TPMBackend) tpm_backends =
     QLIST_HEAD_INITIALIZER(tpm_backends);
diff --git a/trace/qmp.c b/trace/qmp.c
index ccd35cd840..756086c79f 100644
--- a/trace/qmp.c
+++ b/trace/qmp.c
@@ -9,7 +9,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands-trace.h"
 #include "trace/control.h"
 
 
diff --git a/ui/console.c b/ui/console.c
index 36584d039e..a789b8c408 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -26,9 +26,9 @@
 #include "ui/console.h"
 #include "hw/qdev-core.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-ui.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
-#include "qmp-commands.h"
 #include "chardev/char-fe.h"
 #include "trace.h"
 #include "exec/memory.h"
diff --git a/ui/input-legacy.c b/ui/input-legacy.c
index 92b37ccb90..e5d4db1d97 100644
--- a/ui/input-legacy.c
+++ b/ui/input-legacy.c
@@ -23,9 +23,9 @@
  */
 
 #include "qemu/osdep.h"
+#include "qapi/qapi-commands-ui.h"
 #include "sysemu/sysemu.h"
 #include "ui/console.h"
-#include "qmp-commands.h"
 #include "ui/keymaps.h"
 #include "ui/input.h"
 
diff --git a/ui/input.c b/ui/input.c
index 8bef0fb038..51b1019252 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -1,9 +1,9 @@
 #include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/error-report.h"
-#include "qmp-commands.h"
 #include "trace.h"
 #include "ui/input.h"
 #include "ui/console.h"
diff --git a/ui/spice-core.c b/ui/spice-core.c
index e449172fe9..ae8921a201 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -28,14 +28,14 @@
 #include "qemu/queue.h"
 #include "qemu-x509.h"
 #include "qemu/sockets.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-ui.h"
+#include "qapi/qapi-events-ui.h"
 #include "qemu/notify.h"
 #include "qemu/option.h"
 #include "migration/misc.h"
 #include "hw/hw.h"
 #include "ui/spice-display.h"
-#include "qapi-event.h"
 
 /* core bits */
 
diff --git a/ui/vnc.c b/ui/vnc.c
index c715bae1cf..d6329c8bd5 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -36,7 +36,7 @@
 #include "qemu/acl.h"
 #include "qemu/config-file.h"
 #include "qapi/error.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands-ui.h"
 #include "ui/input.h"
 #include "qapi-event.h"
 #include "crypto/hash.h"
diff --git a/ui/vnc.h b/ui/vnc.h
index 1ca062f332..7b29def77d 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -28,6 +28,7 @@
 #define QEMU_VNC_H
 
 #include "qemu-common.h"
+#include "qapi/qapi-types-ui.h"
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "ui/console.h"
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index fbbef69f62..7f13e8a338 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -24,11 +24,11 @@
 #include "monitor/monitor.h"
 #include "qapi/clone-visitor.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-sockets.h"
 #include "qemu/sockets.h"
 #include "qemu/main-loop.h"
 #include "qapi/qobject-input-visitor.h"
 #include "qapi/qobject-output-visitor.h"
-#include "qapi-visit.h"
 #include "qemu/cutils.h"
 
 #ifndef AI_ADDRCONFIG
diff --git a/vl.c b/vl.c
index 21878496ec..4e8287c507 100644
--- a/vl.c
+++ b/vl.c
@@ -97,7 +97,6 @@ int main(int argc, char **argv)
 #include "sysemu/kvm.h"
 #include "sysemu/hax.h"
 #include "qapi/qobject-input-visitor.h"
-#include "qapi-visit.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qemu-options.h"
@@ -122,10 +121,11 @@ int main(int argc, char **argv)
 #include "qapi/string-input-visitor.h"
 #include "qapi/opts-visitor.h"
 #include "qom/object_interfaces.h"
-#include "qapi-event.h"
 #include "exec/semihost.h"
 #include "crypto/init.h"
 #include "sysemu/replay.h"
+#include "qapi/qapi-events-run-state.h"
+#include "qapi/qapi-visit-block-core.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/iothread.h"
 
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (22 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:26   ` Eric Blake
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
                   ` (7 subsequent siblings)
  31 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

The previous commit improved compile time by including less of the
generated QAPI headers.  This is impossible for stuff defined directly
in qapi-schema.json, because that ends up in headers that that pull in
everything.

Move everything but include directives from qapi-schema.json to new
sub-module qapi/misc.json, then include just the "misc" shard where
possible.

It's not possible everywhere, except:

* monitor.c needs qmp-command.h to get qmp_init_marshall()

* monitor.c, ui/vnc.c and the generated qapi-event-FOO.c need
  qapi-event.h to get enum QAPIEvent

Perhaps we'll get rid of those some other day.

Adding a type to qapi/migration.json now recompiles some 120 instead
of 2300 out of 5100 objects.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore                         |    4 +
 Makefile                           |    9 +
 Makefile.objs                      |    4 +
 arch_init.c                        |    2 +-
 balloon.c                          |    2 +-
 block/iscsi.c                      |    2 +-
 cpus.c                             |    2 +-
 dump.c                             |    4 +-
 hmp.c                              |   10 +-
 hw/acpi/core.c                     |    2 +-
 hw/acpi/cpu.c                      |    2 +-
 hw/acpi/memory_hotplug.c           |    2 +-
 hw/acpi/vmgenid.c                  |    2 +-
 hw/core/qdev.c                     |    2 +-
 hw/i386/xen/xen-hvm.c              |    2 +-
 hw/ipmi/ipmi.c                     |    2 +-
 hw/pci/pci-stub.c                  |    2 +-
 hw/pci/pci.c                       |    2 +-
 hw/ppc/spapr_rtc.c                 |    2 +-
 hw/s390x/s390-skeys.c              |    2 +-
 hw/timer/mc146818rtc.c             |    4 +-
 hw/virtio/virtio-balloon.c         |    2 +-
 hw/watchdog/watchdog.c             |    2 +-
 include/hw/qdev-properties.h       |    3 +-
 include/monitor/monitor.h          |    2 +-
 include/sysemu/arch_init.h         |    2 +-
 include/sysemu/balloon.h           |    2 +-
 include/sysemu/dump.h              |    2 +-
 include/sysemu/hostmem.h           |    2 +-
 include/sysemu/replay.h            |    3 +-
 iothread.c                         |    2 +-
 migration/savevm.c                 |    3 +-
 numa.c                             |    4 +-
 qapi-schema.json                   | 3098 +-----------------------------------
 qapi/misc.json                     | 3090 +++++++++++++++++++++++++++++++++++
 qapi/run-state.json                |   10 +
 qdev-monitor.c                     |    2 +-
 qmp.c                              |    4 +-
 stubs/uuid.c                       |    2 +-
 stubs/vmgenid.c                    |    2 +-
 stubs/xen-hvm.c                    |    2 +-
 target/arm/monitor.c               |    3 +-
 target/i386/cpu.c                  |    4 +-
 tests/qmp-test.c                   |    3 +-
 tests/test-qobject-input-visitor.c |    2 +-
 tests/test-visitor-serialization.c |    1 -
 ui/gtk.c                           |    2 +-
 util/qemu-config.c                 |    2 +-
 vl.c                               |    4 +-
 49 files changed, 3181 insertions(+), 3144 deletions(-)
 create mode 100644 qapi/misc.json

diff --git a/.gitignore b/.gitignore
index 42c57998fd..7f162e862f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,7 @@
 /qapi/qapi-commands-crypto.[ch]
 /qapi/qapi-commands-introspect.[ch]
 /qapi/qapi-commands-migration.[ch]
+/qapi/qapi-commands-misc.[ch]
 /qapi/qapi-commands-net.[ch]
 /qapi/qapi-commands-rocker.[ch]
 /qapi/qapi-commands-run-state.[ch]
@@ -53,6 +54,7 @@
 /qapi/qapi-events-crypto.[ch]
 /qapi/qapi-events-introspect.[ch]
 /qapi/qapi-events-migration.[ch]
+/qapi/qapi-events-misc.[ch]
 /qapi/qapi-events-net.[ch]
 /qapi/qapi-events-rocker.[ch]
 /qapi/qapi-events-run-state.[ch]
@@ -68,6 +70,7 @@
 /qapi/qapi-types-crypto.[ch]
 /qapi/qapi-types-introspect.[ch]
 /qapi/qapi-types-migration.[ch]
+/qapi/qapi-types-misc.[ch]
 /qapi/qapi-types-net.[ch]
 /qapi/qapi-types-rocker.[ch]
 /qapi/qapi-types-run-state.[ch]
@@ -84,6 +87,7 @@
 /qapi/qapi-visit-crypto.[ch]
 /qapi/qapi-visit-introspect.[ch]
 /qapi/qapi-visit-migration.[ch]
+/qapi/qapi-visit-misc.[ch]
 /qapi/qapi-visit-net.[ch]
 /qapi/qapi-visit-rocker.[ch]
 /qapi/qapi-visit-run-state.[ch]
diff --git a/Makefile b/Makefile
index ac9a7627a2..50eb194877 100644
--- a/Makefile
+++ b/Makefile
@@ -99,6 +99,7 @@ GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c
 GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c
 GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c
 GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c
+GENERATED_FILES += qapi/qapi-types-misc.h qapi/qapi-types-misc.c
 GENERATED_FILES += qapi/qapi-types-net.h qapi/qapi-types-net.c
 GENERATED_FILES += qapi/qapi-types-rocker.h qapi/qapi-types-rocker.c
 GENERATED_FILES += qapi/qapi-types-run-state.h qapi/qapi-types-run-state.c
@@ -116,6 +117,7 @@ GENERATED_FILES += qapi/qapi-visit-common.h qapi/qapi-visit-common.c
 GENERATED_FILES += qapi/qapi-visit-crypto.h qapi/qapi-visit-crypto.c
 GENERATED_FILES += qapi/qapi-visit-introspect.h qapi/qapi-visit-introspect.c
 GENERATED_FILES += qapi/qapi-visit-migration.h qapi/qapi-visit-migration.c
+GENERATED_FILES += qapi/qapi-visit-misc.h qapi/qapi-visit-misc.c
 GENERATED_FILES += qapi/qapi-visit-net.h qapi/qapi-visit-net.c
 GENERATED_FILES += qapi/qapi-visit-rocker.h qapi/qapi-visit-rocker.c
 GENERATED_FILES += qapi/qapi-visit-run-state.h qapi/qapi-visit-run-state.c
@@ -132,6 +134,7 @@ GENERATED_FILES += qapi/qapi-commands-common.h qapi/qapi-commands-common.c
 GENERATED_FILES += qapi/qapi-commands-crypto.h qapi/qapi-commands-crypto.c
 GENERATED_FILES += qapi/qapi-commands-introspect.h qapi/qapi-commands-introspect.c
 GENERATED_FILES += qapi/qapi-commands-migration.h qapi/qapi-commands-migration.c
+GENERATED_FILES += qapi/qapi-commands-misc.h qapi/qapi-commands-misc.c
 GENERATED_FILES += qapi/qapi-commands-net.h qapi/qapi-commands-net.c
 GENERATED_FILES += qapi/qapi-commands-rocker.h qapi/qapi-commands-rocker.c
 GENERATED_FILES += qapi/qapi-commands-run-state.h qapi/qapi-commands-run-state.c
@@ -148,6 +151,7 @@ GENERATED_FILES += qapi/qapi-events-common.h qapi/qapi-events-common.c
 GENERATED_FILES += qapi/qapi-events-crypto.h qapi/qapi-events-crypto.c
 GENERATED_FILES += qapi/qapi-events-introspect.h qapi/qapi-events-introspect.c
 GENERATED_FILES += qapi/qapi-events-migration.h qapi/qapi-events-migration.c
+GENERATED_FILES += qapi/qapi-events-misc.h qapi/qapi-events-misc.c
 GENERATED_FILES += qapi/qapi-events-net.h qapi/qapi-events-net.c
 GENERATED_FILES += qapi/qapi-events-rocker.h qapi/qapi-events-rocker.c
 GENERATED_FILES += qapi/qapi-events-run-state.h qapi/qapi-events-run-state.c
@@ -574,6 +578,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/crypto.json \
                $(SRC_PATH)/qapi/introspect.json \
                $(SRC_PATH)/qapi/migration.json \
+               $(SRC_PATH)/qapi/misc.json \
                $(SRC_PATH)/qapi/net.json \
                $(SRC_PATH)/qapi/rocker.json \
                $(SRC_PATH)/qapi/run-state.json \
@@ -592,6 +597,7 @@ qapi/qapi-types-common.c qapi/qapi-types-common.h \
 qapi/qapi-types-crypto.c qapi/qapi-types-crypto.h \
 qapi/qapi-types-introspect.c qapi/qapi-types-introspect.h \
 qapi/qapi-types-migration.c qapi/qapi-types-migration.h \
+qapi/qapi-types-misc.c qapi/qapi-types-misc.h \
 qapi/qapi-types-net.c qapi/qapi-types-net.h \
 qapi/qapi-types-rocker.c qapi/qapi-types-rocker.h \
 qapi/qapi-types-run-state.c qapi/qapi-types-run-state.h \
@@ -609,6 +615,7 @@ qapi/qapi-visit-common.c qapi/qapi-visit-common.h \
 qapi/qapi-visit-crypto.c qapi/qapi-visit-crypto.h \
 qapi/qapi-visit-introspect.c qapi/qapi-visit-introspect.h \
 qapi/qapi-visit-migration.c qapi/qapi-visit-migration.h \
+qapi/qapi-visit-misc.c qapi/qapi-visit-misc.h \
 qapi/qapi-visit-net.c qapi/qapi-visit-net.h \
 qapi/qapi-visit-rocker.c qapi/qapi-visit-rocker.h \
 qapi/qapi-visit-run-state.c qapi/qapi-visit-run-state.h \
@@ -625,6 +632,7 @@ qapi/qapi-commands-common.c qapi/qapi-commands-common.h \
 qapi/qapi-commands-crypto.c qapi/qapi-commands-crypto.h \
 qapi/qapi-commands-introspect.c qapi/qapi-commands-introspect.h \
 qapi/qapi-commands-migration.c qapi/qapi-commands-migration.h \
+qapi/qapi-commands-misc.c qapi/qapi-commands-misc.h \
 qapi/qapi-commands-net.c qapi/qapi-commands-net.h \
 qapi/qapi-commands-rocker.c qapi/qapi-commands-rocker.h \
 qapi/qapi-commands-run-state.c qapi/qapi-commands-run-state.h \
@@ -641,6 +649,7 @@ qapi/qapi-events-common.c qapi/qapi-events-common.h \
 qapi/qapi-events-crypto.c qapi/qapi-events-crypto.h \
 qapi/qapi-events-introspect.c qapi/qapi-events-introspect.h \
 qapi/qapi-events-migration.c qapi/qapi-events-migration.h \
+qapi/qapi-events-misc.c qapi/qapi-events-misc.h \
 qapi/qapi-events-net.c qapi/qapi-events-net.h \
 qapi/qapi-events-rocker.c qapi/qapi-events-rocker.h \
 qapi/qapi-events-run-state.c qapi/qapi-events-run-state.h \
diff --git a/Makefile.objs b/Makefile.objs
index 7a55d45669..a7986bbf0b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -11,6 +11,7 @@ util-obj-y += qapi/qapi-types-common.o
 util-obj-y += qapi/qapi-types-crypto.o
 util-obj-y += qapi/qapi-types-introspect.o
 util-obj-y += qapi/qapi-types-migration.o
+util-obj-y += qapi/qapi-types-misc.o
 util-obj-y += qapi/qapi-types-net.o
 util-obj-y += qapi/qapi-types-rocker.o
 util-obj-y += qapi/qapi-types-run-state.o
@@ -28,6 +29,7 @@ util-obj-y += qapi/qapi-visit-common.o
 util-obj-y += qapi/qapi-visit-crypto.o
 util-obj-y += qapi/qapi-visit-introspect.o
 util-obj-y += qapi/qapi-visit-migration.o
+util-obj-y += qapi/qapi-visit-misc.o
 util-obj-y += qapi/qapi-visit-net.o
 util-obj-y += qapi/qapi-visit-rocker.o
 util-obj-y += qapi/qapi-visit-run-state.o
@@ -44,6 +46,7 @@ util-obj-y += qapi/qapi-events-common.o
 util-obj-y += qapi/qapi-events-crypto.o
 util-obj-y += qapi/qapi-events-introspect.o
 util-obj-y += qapi/qapi-events-migration.o
+util-obj-y += qapi/qapi-events-misc.o
 util-obj-y += qapi/qapi-events-net.o
 util-obj-y += qapi/qapi-events-rocker.o
 util-obj-y += qapi/qapi-events-run-state.o
@@ -136,6 +139,7 @@ common-obj-y += qapi/qapi-commands-common.o
 common-obj-y += qapi/qapi-commands-crypto.o
 common-obj-y += qapi/qapi-commands-introspect.o
 common-obj-y += qapi/qapi-commands-migration.o
+common-obj-y += qapi/qapi-commands-misc.o
 common-obj-y += qapi/qapi-commands-net.o
 common-obj-y += qapi/qapi-commands-rocker.o
 common-obj-y += qapi/qapi-commands-run-state.o
diff --git a/arch_init.c b/arch_init.c
index 4c36f2b076..46d03f550d 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -28,9 +28,9 @@
 #include "sysemu/arch_init.h"
 #include "hw/pci/pci.h"
 #include "hw/audio/soundhw.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
-#include "qmp-commands.h"
 #include "hw/acpi/acpi.h"
 #include "qemu/help_option.h"
 
diff --git a/balloon.c b/balloon.c
index d8dd6fe773..6bf0a96813 100644
--- a/balloon.c
+++ b/balloon.c
@@ -30,8 +30,8 @@
 #include "sysemu/kvm.h"
 #include "sysemu/balloon.h"
 #include "trace-root.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qerror.h"
 
 static QEMUBalloonEvent *balloon_event_fn;
diff --git a/block/iscsi.c b/block/iscsi.c
index 9f99ae5e07..c727bfa788 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -37,8 +37,8 @@
 #include "qemu/iov.h"
 #include "qemu/option.h"
 #include "qemu/uuid.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "crypto/secret.h"
diff --git a/cpus.c b/cpus.c
index ddb7f9b811..a4c08ba6e2 100644
--- a/cpus.c
+++ b/cpus.c
@@ -27,6 +27,7 @@
 #include "cpu.h"
 #include "monitor/monitor.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qapi-events-run-state.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
@@ -39,7 +40,6 @@
 #include "sysemu/hax.h"
 #include "sysemu/hvf.h"
 #include "sysemu/whpx.h"
-#include "qmp-commands.h"
 #include "exec/exec-all.h"
 
 #include "qemu/thread.h"
diff --git a/dump.c b/dump.c
index 7b13baa413..097e60b2b3 100644
--- a/dump.c
+++ b/dump.c
@@ -23,9 +23,9 @@
 #include "sysemu/memory_mapping.h"
 #include "sysemu/cpus.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-events-misc.h"
 #include "qapi/qmp/qerror.h"
-#include "qmp-commands.h"
-#include "qapi-event.h"
 #include "qemu/error-report.h"
 #include "hw/misc/vmcoreinfo.h"
 
diff --git a/hmp.c b/hmp.c
index a49f4c126e..c86946866b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -23,13 +23,21 @@
 #include "qemu/config-file.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
-#include "qmp-commands.h"
 #include "qemu/sockets.h"
 #include "monitor/monitor.h"
 #include "monitor/qdev.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
 #include "qapi-builtin-visit.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/qapi-commands-char.h"
+#include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-net.h"
+#include "qapi/qapi-commands-rocker.h"
+#include "qapi/qapi-commands-run-state.h"
+#include "qapi/qapi-commands-tpm.h"
+#include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/string-input-visitor.h"
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 5d4ce925dc..b8d39012cd 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -28,7 +28,7 @@
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
 #include "qapi/qapi-events-run-state.h"
-#include "qapi-visit.h"
+#include "qapi/qapi-visit-misc.h"
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index a233fe17cf..5ae595ecbe 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -2,7 +2,7 @@
 #include "hw/boards.h"
 #include "hw/acpi/cpu.h"
 #include "qapi/error.h"
-#include "qapi-event.h"
+#include "qapi/qapi-events-misc.h"
 #include "trace.h"
 #include "sysemu/numa.h"
 
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index ea958a0e99..0ff1712c4c 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -5,8 +5,8 @@
 #include "hw/boards.h"
 #include "hw/qdev-core.h"
 #include "trace.h"
-#include "qapi-event.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-misc.h"
 
 #define MEMORY_SLOTS_NUMBER          "MDNR"
 #define MEMORY_HOTPLUG_IO_REGION     "HPMR"
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index f25eafc0ec..d78b579a20 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -12,7 +12,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands-misc.h"
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/aml-build.h"
 #include "hw/acpi/vmgenid.h"
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 7ed1f431f0..7635cf55fd 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -29,6 +29,7 @@
 #include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-misc.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
@@ -36,7 +37,6 @@
 #include "hw/hotplug.h"
 #include "hw/boards.h"
 #include "hw/sysbus.h"
-#include "qapi-event.h"
 
 bool qdev_hotplug = false;
 static bool qdev_hot_added = false;
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index bfdbe55580..f24b7d4923 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -16,8 +16,8 @@
 #include "hw/i386/apic-msidef.h"
 #include "hw/xen/xen_common.h"
 #include "hw/xen/xen_backend.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/error-report.h"
 #include "qemu/range.h"
 #include "sysemu/xen-mapcache.h"
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index adbbf6e4a6..9be281fd87 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -26,9 +26,9 @@
 #include "hw/hw.h"
 #include "hw/ipmi/ipmi.h"
 #include "sysemu/sysemu.h"
-#include "qmp-commands.h"
 #include "qom/object_interfaces.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/visitor.h"
 
 static uint32_t ipmi_current_uuid = 1;
diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c
index 74ce7316da..b941a0e842 100644
--- a/hw/pci/pci-stub.c
+++ b/hw/pci/pci-stub.c
@@ -22,9 +22,9 @@
 #include "sysemu/sysemu.h"
 #include "monitor/monitor.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qerror.h"
 #include "hw/pci/pci.h"
-#include "qmp-commands.h"
 #include "hw/pci/msi.h"
 
 bool msi_nonbroken;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 239f73d711..7b9745ca77 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -34,7 +34,6 @@
 #include "hw/loader.h"
 #include "qemu/error-report.h"
 #include "qemu/range.h"
-#include "qmp-commands.h"
 #include "trace.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
@@ -42,6 +41,7 @@
 #include "hw/hotplug.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/cutils.h"
 
 //#define DEBUG_PCI
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index cfdb274bfd..a37360537e 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -30,8 +30,8 @@
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "hw/ppc/spapr.h"
-#include "qapi-event.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-misc.h"
 #include "qemu/cutils.h"
 
 void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns)
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index bdb6c18a0f..76241c240e 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -11,9 +11,9 @@
 
 #include "qemu/osdep.h"
 #include "hw/boards.h"
-#include "qmp-commands.h"
 #include "hw/s390x/storage-keys.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qemu/error-report.h"
 #include "sysemu/kvm.h"
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 9d93a16e0f..6f1f723b1f 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -31,9 +31,9 @@
 #include "sysemu/replay.h"
 #include "hw/timer/mc146818rtc.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-events-misc.h"
 #include "qapi/visitor.h"
-#include "qapi-event.h"
-#include "qmp-commands.h"
 
 #ifdef TARGET_I386
 #include "hw/i386/apic.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index e05df206fc..5d98902831 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -24,8 +24,8 @@
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 #include "qapi/error.h"
+#include "qapi/qapi-events-misc.h"
 #include "qapi/visitor.h"
-#include "qapi-event.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index c7843d5748..6e8ba061d8 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -24,12 +24,12 @@
 #include "qemu/config-file.h"
 #include "qemu/queue.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-run-state.h"
 #include "qapi/qapi-events-run-state.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/watchdog.h"
 #include "hw/nmi.h"
 #include "qemu/help_option.h"
-#include "qmp-commands.h"
 
 static WatchdogAction watchdog_action = WATCHDOG_ACTION_RESET;
 static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 40c2c8acb1..b2ad8e9faa 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -1,7 +1,8 @@
 #ifndef QEMU_QDEV_PROPERTIES_H
 #define QEMU_QDEV_PROPERTIES_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-block.h"
+#include "qapi/qapi-types-misc.h"
 #include "hw/qdev-core.h"
 
 /*** qdev-properties.c ***/
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 50f7cea057..d1024d4bdc 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -3,7 +3,7 @@
 
 #include "qemu-common.h"
 #include "block/block.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
 #include "qemu/readline.h"
 
 extern Monitor *cur_mon;
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index d40d882e38..cecd494159 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_ARCH_INIT_H
 #define QEMU_ARCH_INIT_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
 
 enum {
     QEMU_ARCH_ALL = -1,
diff --git a/include/sysemu/balloon.h b/include/sysemu/balloon.h
index af49e19c78..66543ae8f4 100644
--- a/include/sysemu/balloon.h
+++ b/include/sysemu/balloon.h
@@ -14,7 +14,7 @@
 #ifndef QEMU_BALLOON_H
 #define QEMU_BALLOON_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
 
 typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
 typedef void (QEMUBalloonStatus)(void *opaque, BalloonInfo *info);
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 2424e31425..d824bc0941 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -14,7 +14,7 @@
 #ifndef DUMP_H
 #define DUMP_H
 
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
 
 #define MAKEDUMPFILE_SIGNATURE      "makedumpfile"
 #define MAX_SIZE_MDF_HEADER         (4096) /* max size of makedumpfile_header */
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index 6424f96df9..dc3ac3d301 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -14,7 +14,7 @@
 #define SYSEMU_HOSTMEM_H
 
 #include "sysemu/sysemu.h" /* for MAX_NODES */
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
 #include "qom/object.h"
 #include "exec/memory.h"
 #include "qemu/bitmap.h"
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index fb533ed9b6..c0204e641c 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -13,7 +13,8 @@
  */
 
 #include "sysemu.h"
-#include "qapi-types.h"
+#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-types-ui.h"
 
 /* replay clock kinds */
 enum ReplayClockKind {
diff --git a/iothread.c b/iothread.c
index 4b9bbde4cd..2ec5a3bffe 100644
--- a/iothread.c
+++ b/iothread.c
@@ -18,8 +18,8 @@
 #include "block/aio.h"
 #include "block/block.h"
 #include "sysemu/iothread.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/error-report.h"
 #include "qemu/rcu.h"
 #include "qemu/main-loop.h"
diff --git a/migration/savevm.c b/migration/savevm.c
index 3f611c02e8..0d42de293d 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -41,12 +41,13 @@
 #include "savevm.h"
 #include "postcopy-ram.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
 #include "sysemu/cpus.h"
 #include "exec/memory.h"
 #include "exec/target_page.h"
-#include "qmp-commands.h"
 #include "trace.h"
 #include "qemu/iov.h"
 #include "block/snapshot.h"
diff --git a/numa.c b/numa.c
index 7e0e789b02..5d7529c1d9 100644
--- a/numa.c
+++ b/numa.c
@@ -29,12 +29,12 @@
 #include "qemu/bitmap.h"
 #include "qom/cpu.h"
 #include "qemu/error-report.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-visit-misc.h"
 #include "hw/boards.h"
 #include "sysemu/hostmem.h"
-#include "qmp-commands.h"
 #include "hw/mem/pc-dimm.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
diff --git a/qapi-schema.json b/qapi-schema.json
index 0d651c8399..689d06c530 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -92,3100 +92,4 @@
 { 'include': 'qapi/transaction.json' }
 { 'include': 'qapi/trace.json' }
 { 'include': 'qapi/introspect.json' }
-
-##
-# = Miscellanea
-##
-
-##
-# @qmp_capabilities:
-#
-# Enable QMP capabilities.
-#
-# Arguments: None.
-#
-# Example:
-#
-# -> { "execute": "qmp_capabilities" }
-# <- { "return": {} }
-#
-# Notes: This command is valid exactly when first connecting: it must be
-# issued before any other command will be accepted, and will fail once the
-# monitor is accepting other commands. (see qemu docs/interop/qmp-spec.txt)
-#
-# Since: 0.13
-#
-##
-{ 'command': 'qmp_capabilities' }
-
-##
-# @VersionTriple:
-#
-# A three-part version number.
-#
-# @major:  The major version number.
-#
-# @minor:  The minor version number.
-#
-# @micro:  The micro version number.
-#
-# Since: 2.4
-##
-{ 'struct': 'VersionTriple',
-  'data': {'major': 'int', 'minor': 'int', 'micro': 'int'} }
-
-
-##
-# @VersionInfo:
-#
-# A description of QEMU's version.
-#
-# @qemu:        The version of QEMU.  By current convention, a micro
-#               version of 50 signifies a development branch.  A micro version
-#               greater than or equal to 90 signifies a release candidate for
-#               the next minor version.  A micro version of less than 50
-#               signifies a stable release.
-#
-# @package:     QEMU will always set this field to an empty string.  Downstream
-#               versions of QEMU should set this to a non-empty string.  The
-#               exact format depends on the downstream however it highly
-#               recommended that a unique name is used.
-#
-# Since: 0.14.0
-##
-{ 'struct': 'VersionInfo',
-  'data': {'qemu': 'VersionTriple', 'package': 'str'} }
-
-##
-# @query-version:
-#
-# Returns the current version of QEMU.
-#
-# Returns:  A @VersionInfo object describing the current version of QEMU.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-version" }
-# <- {
-#       "return":{
-#          "qemu":{
-#             "major":0,
-#             "minor":11,
-#             "micro":5
-#          },
-#          "package":""
-#       }
-#    }
-#
-##
-{ 'command': 'query-version', 'returns': 'VersionInfo' }
-
-##
-# @CommandInfo:
-#
-# Information about a QMP command
-#
-# @name: The command name
-#
-# Since: 0.14.0
-##
-{ 'struct': 'CommandInfo', 'data': {'name': 'str'} }
-
-##
-# @query-commands:
-#
-# Return a list of supported QMP commands by this server
-#
-# Returns: A list of @CommandInfo for all supported commands
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-commands" }
-# <- {
-#      "return":[
-#         {
-#            "name":"query-balloon"
-#         },
-#         {
-#            "name":"system_powerdown"
-#         }
-#      ]
-#    }
-#
-# Note: This example has been shortened as the real response is too long.
-#
-##
-{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
-
-##
-# @LostTickPolicy:
-#
-# Policy for handling lost ticks in timer devices.
-#
-# @discard: throw away the missed tick(s) and continue with future injection
-#           normally.  Guest time may be delayed, unless the OS has explicit
-#           handling of lost ticks
-#
-# @delay: continue to deliver ticks at the normal rate.  Guest time will be
-#         delayed due to the late tick
-#
-# @merge: merge the missed tick(s) into one tick and inject.  Guest time
-#         may be delayed, depending on how the OS reacts to the merging
-#         of ticks
-#
-# @slew: deliver ticks at a higher rate to catch up with the missed tick. The
-#        guest time should not be delayed once catchup is complete.
-#
-# Since: 2.0
-##
-{ 'enum': 'LostTickPolicy',
-  'data': ['discard', 'delay', 'merge', 'slew' ] }
-
-##
-# @add_client:
-#
-# Allow client connections for VNC, Spice and socket based
-# character devices to be passed in to QEMU via SCM_RIGHTS.
-#
-# @protocol: protocol name. Valid names are "vnc", "spice" or the
-#            name of a character device (eg. from -chardev id=XXXX)
-#
-# @fdname: file descriptor name previously passed via 'getfd' command
-#
-# @skipauth: whether to skip authentication. Only applies
-#            to "vnc" and "spice" protocols
-#
-# @tls: whether to perform TLS. Only applies to the "spice"
-#       protocol
-#
-# Returns: nothing on success.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "add_client", "arguments": { "protocol": "vnc",
-#                                              "fdname": "myclient" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'add_client',
-  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',
-            '*tls': 'bool' } }
-
-##
-# @NameInfo:
-#
-# Guest name information.
-#
-# @name: The name of the guest
-#
-# Since: 0.14.0
-##
-{ 'struct': 'NameInfo', 'data': {'*name': 'str'} }
-
-##
-# @query-name:
-#
-# Return the name information of a guest.
-#
-# Returns: @NameInfo of the guest
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-name" }
-# <- { "return": { "name": "qemu-name" } }
-#
-##
-{ 'command': 'query-name', 'returns': 'NameInfo' }
-
-##
-# @KvmInfo:
-#
-# Information about support for KVM acceleration
-#
-# @enabled: true if KVM acceleration is active
-#
-# @present: true if KVM acceleration is built into this executable
-#
-# Since: 0.14.0
-##
-{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
-
-##
-# @query-kvm:
-#
-# Returns information about KVM acceleration
-#
-# Returns: @KvmInfo
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-kvm" }
-# <- { "return": { "enabled": true, "present": true } }
-#
-##
-{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
-
-##
-# @UuidInfo:
-#
-# Guest UUID information (Universally Unique Identifier).
-#
-# @UUID: the UUID of the guest
-#
-# Since: 0.14.0
-#
-# Notes: If no UUID was specified for the guest, a null UUID is returned.
-##
-{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} }
-
-##
-# @query-uuid:
-#
-# Query the guest UUID information.
-#
-# Returns: The @UuidInfo for the guest
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-uuid" }
-# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
-#
-##
-{ 'command': 'query-uuid', 'returns': 'UuidInfo' }
-
-##
-# @EventInfo:
-#
-# Information about a QMP event
-#
-# @name: The event name
-#
-# Since: 1.2.0
-##
-{ 'struct': 'EventInfo', 'data': {'name': 'str'} }
-
-##
-# @query-events:
-#
-# Return a list of supported QMP events by this server
-#
-# Returns: A list of @EventInfo for all supported events
-#
-# Since: 1.2.0
-#
-# Example:
-#
-# -> { "execute": "query-events" }
-# <- {
-#      "return": [
-#          {
-#             "name":"SHUTDOWN"
-#          },
-#          {
-#             "name":"RESET"
-#          }
-#       ]
-#    }
-#
-# Note: This example has been shortened as the real response is too long.
-#
-##
-{ 'command': 'query-events', 'returns': ['EventInfo'] }
-
-##
-# @CpuInfoArch:
-#
-# An enumeration of cpu types that enable additional information during
-# @query-cpus.
-#
-# Since: 2.6
-##
-{ 'enum': 'CpuInfoArch',
-  'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 'other' ] }
-
-##
-# @CpuInfo:
-#
-# Information about a virtual CPU
-#
-# @CPU: the index of the virtual CPU
-#
-# @current: this only exists for backwards compatibility and should be ignored
-#
-# @halted: true if the virtual CPU is in the halt state.  Halt usually refers
-#          to a processor specific low power mode.
-#
-# @qom_path: path to the CPU object in the QOM tree (since 2.4)
-#
-# @thread_id: ID of the underlying host thread
-#
-# @props: properties describing to which node/socket/core/thread
-#         virtual CPU belongs to, provided if supported by board (since 2.10)
-#
-# @arch: architecture of the cpu, which determines which additional fields
-#        will be listed (since 2.6)
-#
-# Since: 0.14.0
-#
-# Notes: @halted is a transient state that changes frequently.  By the time the
-#        data is sent to the client, the guest may no longer be halted.
-##
-{ 'union': 'CpuInfo',
-  'base': {'CPU': 'int', 'current': 'bool', 'halted': 'bool',
-           'qom_path': 'str', 'thread_id': 'int',
-           '*props': 'CpuInstanceProperties', 'arch': 'CpuInfoArch' },
-  'discriminator': 'arch',
-  'data': { 'x86': 'CpuInfoX86',
-            'sparc': 'CpuInfoSPARC',
-            'ppc': 'CpuInfoPPC',
-            'mips': 'CpuInfoMIPS',
-            'tricore': 'CpuInfoTricore',
-            'other': 'CpuInfoOther' } }
-
-##
-# @CpuInfoX86:
-#
-# Additional information about a virtual i386 or x86_64 CPU
-#
-# @pc: the 64-bit instruction pointer
-#
-# Since: 2.6
-##
-{ 'struct': 'CpuInfoX86', 'data': { 'pc': 'int' } }
-
-##
-# @CpuInfoSPARC:
-#
-# Additional information about a virtual SPARC CPU
-#
-# @pc: the PC component of the instruction pointer
-#
-# @npc: the NPC component of the instruction pointer
-#
-# Since: 2.6
-##
-{ 'struct': 'CpuInfoSPARC', 'data': { 'pc': 'int', 'npc': 'int' } }
-
-##
-# @CpuInfoPPC:
-#
-# Additional information about a virtual PPC CPU
-#
-# @nip: the instruction pointer
-#
-# Since: 2.6
-##
-{ 'struct': 'CpuInfoPPC', 'data': { 'nip': 'int' } }
-
-##
-# @CpuInfoMIPS:
-#
-# Additional information about a virtual MIPS CPU
-#
-# @PC: the instruction pointer
-#
-# Since: 2.6
-##
-{ 'struct': 'CpuInfoMIPS', 'data': { 'PC': 'int' } }
-
-##
-# @CpuInfoTricore:
-#
-# Additional information about a virtual Tricore CPU
-#
-# @PC: the instruction pointer
-#
-# Since: 2.6
-##
-{ 'struct': 'CpuInfoTricore', 'data': { 'PC': 'int' } }
-
-##
-# @CpuInfoOther:
-#
-# No additional information is available about the virtual CPU
-#
-# Since: 2.6
-#
-##
-{ 'struct': 'CpuInfoOther', 'data': { } }
-
-##
-# @query-cpus:
-#
-# Returns a list of information about each virtual CPU.
-#
-# Returns: a list of @CpuInfo for each virtual CPU
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-cpus" }
-# <- { "return": [
-#          {
-#             "CPU":0,
-#             "current":true,
-#             "halted":false,
-#             "qom_path":"/machine/unattached/device[0]",
-#             "arch":"x86",
-#             "pc":3227107138,
-#             "thread_id":3134
-#          },
-#          {
-#             "CPU":1,
-#             "current":false,
-#             "halted":true,
-#             "qom_path":"/machine/unattached/device[2]",
-#             "arch":"x86",
-#             "pc":7108165,
-#             "thread_id":3135
-#          }
-#       ]
-#    }
-#
-##
-{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }
-
-##
-# @IOThreadInfo:
-#
-# Information about an iothread
-#
-# @id: the identifier of the iothread
-#
-# @thread-id: ID of the underlying host thread
-#
-# @poll-max-ns: maximum polling time in ns, 0 means polling is disabled
-#               (since 2.9)
-#
-# @poll-grow: how many ns will be added to polling time, 0 means that it's not
-#             configured (since 2.9)
-#
-# @poll-shrink: how many ns will be removed from polling time, 0 means that
-#               it's not configured (since 2.9)
-#
-# Since: 2.0
-##
-{ 'struct': 'IOThreadInfo',
-  'data': {'id': 'str',
-           'thread-id': 'int',
-           'poll-max-ns': 'int',
-           'poll-grow': 'int',
-           'poll-shrink': 'int' } }
-
-##
-# @query-iothreads:
-#
-# Returns a list of information about each iothread.
-#
-# Note: this list excludes the QEMU main loop thread, which is not declared
-# using the -object iothread command-line option.  It is always the main thread
-# of the process.
-#
-# Returns: a list of @IOThreadInfo for each iothread
-#
-# Since: 2.0
-#
-# Example:
-#
-# -> { "execute": "query-iothreads" }
-# <- { "return": [
-#          {
-#             "id":"iothread0",
-#             "thread-id":3134
-#          },
-#          {
-#             "id":"iothread1",
-#             "thread-id":3135
-#          }
-#       ]
-#    }
-#
-##
-{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'] }
-
-##
-# @BalloonInfo:
-#
-# Information about the guest balloon device.
-#
-# @actual: the number of bytes the balloon currently contains
-#
-# Since: 0.14.0
-#
-##
-{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } }
-
-##
-# @query-balloon:
-#
-# Return information about the balloon device.
-#
-# Returns: @BalloonInfo on success
-#
-#          If the balloon driver is enabled but not functional because the KVM
-#          kernel module cannot support it, KvmMissingCap
-#
-#          If no balloon device is present, DeviceNotActive
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-balloon" }
-# <- { "return": {
-#          "actual": 1073741824,
-#       }
-#    }
-#
-##
-{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }
-
-##
-# @BALLOON_CHANGE:
-#
-# Emitted when the guest changes the actual BALLOON level. This value is
-# equivalent to the @actual field return by the 'query-balloon' command
-#
-# @actual: actual level of the guest memory balloon in bytes
-#
-# Note: this event is rate-limited.
-#
-# Since: 1.2
-#
-# Example:
-#
-# <- { "event": "BALLOON_CHANGE",
-#      "data": { "actual": 944766976 },
-#      "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-#
-##
-{ 'event': 'BALLOON_CHANGE',
-  'data': { 'actual': 'int' } }
-
-##
-# @PciMemoryRange:
-#
-# A PCI device memory region
-#
-# @base: the starting address (guest physical)
-#
-# @limit: the ending address (guest physical)
-#
-# Since: 0.14.0
-##
-{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }
-
-##
-# @PciMemoryRegion:
-#
-# Information about a PCI device I/O region.
-#
-# @bar: the index of the Base Address Register for this region
-#
-# @type: 'io' if the region is a PIO region
-#        'memory' if the region is a MMIO region
-#
-# @size: memory size
-#
-# @prefetch: if @type is 'memory', true if the memory is prefetchable
-#
-# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit
-#
-# Since: 0.14.0
-##
-{ 'struct': 'PciMemoryRegion',
-  'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int',
-           '*prefetch': 'bool', '*mem_type_64': 'bool' } }
-
-##
-# @PciBusInfo:
-#
-# Information about a bus of a PCI Bridge device
-#
-# @number: primary bus interface number.  This should be the number of the
-#          bus the device resides on.
-#
-# @secondary: secondary bus interface number.  This is the number of the
-#             main bus for the bridge
-#
-# @subordinate: This is the highest number bus that resides below the
-#               bridge.
-#
-# @io_range: The PIO range for all devices on this bridge
-#
-# @memory_range: The MMIO range for all devices on this bridge
-#
-# @prefetchable_range: The range of prefetchable MMIO for all devices on
-#                      this bridge
-#
-# Since: 2.4
-##
-{ 'struct': 'PciBusInfo',
-  'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int',
-           'io_range': 'PciMemoryRange',
-           'memory_range': 'PciMemoryRange',
-           'prefetchable_range': 'PciMemoryRange' } }
-
-##
-# @PciBridgeInfo:
-#
-# Information about a PCI Bridge device
-#
-# @bus: information about the bus the device resides on
-#
-# @devices: a list of @PciDeviceInfo for each device on this bridge
-#
-# Since: 0.14.0
-##
-{ 'struct': 'PciBridgeInfo',
-  'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} }
-
-##
-# @PciDeviceClass:
-#
-# Information about the Class of a PCI device
-#
-# @desc: a string description of the device's class
-#
-# @class: the class code of the device
-#
-# Since: 2.4
-##
-{ 'struct': 'PciDeviceClass',
-  'data': {'*desc': 'str', 'class': 'int'} }
-
-##
-# @PciDeviceId:
-#
-# Information about the Id of a PCI device
-#
-# @device: the PCI device id
-#
-# @vendor: the PCI vendor id
-#
-# Since: 2.4
-##
-{ 'struct': 'PciDeviceId',
-  'data': {'device': 'int', 'vendor': 'int'} }
-
-##
-# @PciDeviceInfo:
-#
-# Information about a PCI device
-#
-# @bus: the bus number of the device
-#
-# @slot: the slot the device is located in
-#
-# @function: the function of the slot used by the device
-#
-# @class_info: the class of the device
-#
-# @id: the PCI device id
-#
-# @irq: if an IRQ is assigned to the device, the IRQ number
-#
-# @qdev_id: the device name of the PCI device
-#
-# @pci_bridge: if the device is a PCI bridge, the bridge information
-#
-# @regions: a list of the PCI I/O regions associated with the device
-#
-# Notes: the contents of @class_info.desc are not stable and should only be
-#        treated as informational.
-#
-# Since: 0.14.0
-##
-{ 'struct': 'PciDeviceInfo',
-  'data': {'bus': 'int', 'slot': 'int', 'function': 'int',
-           'class_info': 'PciDeviceClass', 'id': 'PciDeviceId',
-           '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo',
-           'regions': ['PciMemoryRegion']} }
-
-##
-# @PciInfo:
-#
-# Information about a PCI bus
-#
-# @bus: the bus index
-#
-# @devices: a list of devices on this bus
-#
-# Since: 0.14.0
-##
-{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }
-
-##
-# @query-pci:
-#
-# Return information about the PCI bus topology of the guest.
-#
-# Returns: a list of @PciInfo for each PCI bus. Each bus is
-# represented by a json-object, which has a key with a json-array of
-# all PCI devices attached to it. Each device is represented by a
-# json-object.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "query-pci" }
-# <- { "return": [
-#          {
-#             "bus": 0,
-#             "devices": [
-#                {
-#                   "bus": 0,
-#                   "qdev_id": "",
-#                   "slot": 0,
-#                   "class_info": {
-#                      "class": 1536,
-#                      "desc": "Host bridge"
-#                   },
-#                   "id": {
-#                      "device": 32902,
-#                      "vendor": 4663
-#                   },
-#                   "function": 0,
-#                   "regions": [
-#                   ]
-#                },
-#                {
-#                   "bus": 0,
-#                   "qdev_id": "",
-#                   "slot": 1,
-#                   "class_info": {
-#                      "class": 1537,
-#                      "desc": "ISA bridge"
-#                   },
-#                   "id": {
-#                      "device": 32902,
-#                      "vendor": 28672
-#                   },
-#                   "function": 0,
-#                   "regions": [
-#                   ]
-#                },
-#                {
-#                   "bus": 0,
-#                   "qdev_id": "",
-#                   "slot": 1,
-#                   "class_info": {
-#                      "class": 257,
-#                      "desc": "IDE controller"
-#                   },
-#                   "id": {
-#                      "device": 32902,
-#                      "vendor": 28688
-#                   },
-#                   "function": 1,
-#                   "regions": [
-#                      {
-#                         "bar": 4,
-#                         "size": 16,
-#                         "address": 49152,
-#                         "type": "io"
-#                      }
-#                   ]
-#                },
-#                {
-#                   "bus": 0,
-#                   "qdev_id": "",
-#                   "slot": 2,
-#                   "class_info": {
-#                      "class": 768,
-#                      "desc": "VGA controller"
-#                   },
-#                   "id": {
-#                      "device": 4115,
-#                      "vendor": 184
-#                   },
-#                   "function": 0,
-#                   "regions": [
-#                      {
-#                         "prefetch": true,
-#                         "mem_type_64": false,
-#                         "bar": 0,
-#                         "size": 33554432,
-#                         "address": 4026531840,
-#                         "type": "memory"
-#                      },
-#                      {
-#                         "prefetch": false,
-#                         "mem_type_64": false,
-#                         "bar": 1,
-#                         "size": 4096,
-#                         "address": 4060086272,
-#                         "type": "memory"
-#                      },
-#                      {
-#                         "prefetch": false,
-#                         "mem_type_64": false,
-#                         "bar": 6,
-#                         "size": 65536,
-#                         "address": -1,
-#                         "type": "memory"
-#                      }
-#                   ]
-#                },
-#                {
-#                   "bus": 0,
-#                   "qdev_id": "",
-#                   "irq": 11,
-#                   "slot": 4,
-#                   "class_info": {
-#                      "class": 1280,
-#                      "desc": "RAM controller"
-#                   },
-#                   "id": {
-#                      "device": 6900,
-#                      "vendor": 4098
-#                   },
-#                   "function": 0,
-#                   "regions": [
-#                      {
-#                         "bar": 0,
-#                         "size": 32,
-#                         "address": 49280,
-#                         "type": "io"
-#                      }
-#                   ]
-#                }
-#             ]
-#          }
-#       ]
-#    }
-#
-# Note: This example has been shortened as the real response is too long.
-#
-##
-{ 'command': 'query-pci', 'returns': ['PciInfo'] }
-
-##
-# @quit:
-#
-# This command will cause the QEMU process to exit gracefully.  While every
-# attempt is made to send the QMP response before terminating, this is not
-# guaranteed.  When using this interface, a premature EOF would not be
-# unexpected.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "quit" }
-# <- { "return": {} }
-##
-{ 'command': 'quit' }
-
-##
-# @stop:
-#
-# Stop all guest VCPU execution.
-#
-# Since:  0.14.0
-#
-# Notes:  This function will succeed even if the guest is already in the stopped
-#         state.  In "inmigrate" state, it will ensure that the guest
-#         remains paused once migration finishes, as if the -S option was
-#         passed on the command line.
-#
-# Example:
-#
-# -> { "execute": "stop" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'stop' }
-
-##
-# @system_reset:
-#
-# Performs a hard reset of a guest.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "system_reset" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'system_reset' }
-
-##
-# @system_powerdown:
-#
-# Requests that a guest perform a powerdown operation.
-#
-# Since: 0.14.0
-#
-# Notes: A guest may or may not respond to this command.  This command
-#        returning does not indicate that a guest has accepted the request or
-#        that it has shut down.  Many guests will respond to this command by
-#        prompting the user in some way.
-# Example:
-#
-# -> { "execute": "system_powerdown" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'system_powerdown' }
-
-##
-# @cpu-add:
-#
-# Adds CPU with specified ID
-#
-# @id: ID of CPU to be created, valid values [0..max_cpus)
-#
-# Returns: Nothing on success
-#
-# Since: 1.5
-#
-# Example:
-#
-# -> { "execute": "cpu-add", "arguments": { "id": 2 } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'cpu-add', 'data': {'id': 'int'} }
-
-##
-# @memsave:
-#
-# Save a portion of guest memory to a file.
-#
-# @val: the virtual address of the guest to start from
-#
-# @size: the size of memory region to save
-#
-# @filename: the file to save the memory to as binary data
-#
-# @cpu-index: the index of the virtual CPU to use for translating the
-#                       virtual address (defaults to CPU 0)
-#
-# Returns: Nothing on success
-#
-# Since: 0.14.0
-#
-# Notes: Errors were not reliably returned until 1.1
-#
-# Example:
-#
-# -> { "execute": "memsave",
-#      "arguments": { "val": 10,
-#                     "size": 100,
-#                     "filename": "/tmp/virtual-mem-dump" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'memsave',
-  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
-
-##
-# @pmemsave:
-#
-# Save a portion of guest physical memory to a file.
-#
-# @val: the physical address of the guest to start from
-#
-# @size: the size of memory region to save
-#
-# @filename: the file to save the memory to as binary data
-#
-# Returns: Nothing on success
-#
-# Since: 0.14.0
-#
-# Notes: Errors were not reliably returned until 1.1
-#
-# Example:
-#
-# -> { "execute": "pmemsave",
-#      "arguments": { "val": 10,
-#                     "size": 100,
-#                     "filename": "/tmp/physical-mem-dump" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'pmemsave',
-  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
-
-##
-# @cont:
-#
-# Resume guest VCPU execution.
-#
-# Since:  0.14.0
-#
-# Returns:  If successful, nothing
-#
-# Notes:  This command will succeed if the guest is currently running.  It
-#         will also succeed if the guest is in the "inmigrate" state; in
-#         this case, the effect of the command is to make sure the guest
-#         starts once migration finishes, removing the effect of the -S
-#         command line option if it was passed.
-#
-# Example:
-#
-# -> { "execute": "cont" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'cont' }
-
-##
-# @system_wakeup:
-#
-# Wakeup guest from suspend.  Does nothing in case the guest isn't suspended.
-#
-# Since:  1.1
-#
-# Returns:  nothing.
-#
-# Example:
-#
-# -> { "execute": "system_wakeup" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'system_wakeup' }
-
-##
-# @inject-nmi:
-#
-# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64).
-# The command fails when the guest doesn't support injecting.
-#
-# Returns:  If successful, nothing
-#
-# Since:  0.14.0
-#
-# Note: prior to 2.1, this command was only supported for x86 and s390 VMs
-#
-# Example:
-#
-# -> { "execute": "inject-nmi" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'inject-nmi' }
-
-##
-# @balloon:
-#
-# Request the balloon driver to change its balloon size.
-#
-# @value: the target size of the balloon in bytes
-#
-# Returns: Nothing on success
-#          If the balloon driver is enabled but not functional because the KVM
-#            kernel module cannot support it, KvmMissingCap
-#          If no balloon device is present, DeviceNotActive
-#
-# Notes: This command just issues a request to the guest.  When it returns,
-#        the balloon size may not have changed.  A guest can change the balloon
-#        size independent of this command.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "balloon", "arguments": { "value": 536870912 } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'balloon', 'data': {'value': 'int'} }
-
-##
-# @human-monitor-command:
-#
-# Execute a command on the human monitor and return the output.
-#
-# @command-line: the command to execute in the human monitor
-#
-# @cpu-index: The CPU to use for commands that require an implicit CPU
-#
-# Returns: the output of the command as a string
-#
-# Since: 0.14.0
-#
-# Notes: This command only exists as a stop-gap.  Its use is highly
-#        discouraged.  The semantics of this command are not
-#        guaranteed: this means that command names, arguments and
-#        responses can change or be removed at ANY time.  Applications
-#        that rely on long term stability guarantees should NOT
-#        use this command.
-#
-#        Known limitations:
-#
-#        * This command is stateless, this means that commands that depend
-#          on state information (such as getfd) might not work
-#
-#        * Commands that prompt the user for data don't currently work
-#
-# Example:
-#
-# -> { "execute": "human-monitor-command",
-#      "arguments": { "command-line": "info kvm" } }
-# <- { "return": "kvm support: enabled\r\n" }
-#
-##
-{ 'command': 'human-monitor-command',
-  'data': {'command-line': 'str', '*cpu-index': 'int'},
-  'returns': 'str' }
-
-##
-# @ObjectPropertyInfo:
-#
-# @name: the name of the property
-#
-# @type: the type of the property.  This will typically come in one of four
-#        forms:
-#
-#        1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'.
-#           These types are mapped to the appropriate JSON type.
-#
-#        2) A child type in the form 'child<subtype>' where subtype is a qdev
-#           device type name.  Child properties create the composition tree.
-#
-#        3) A link type in the form 'link<subtype>' where subtype is a qdev
-#           device type name.  Link properties form the device model graph.
-#
-# Since: 1.2
-##
-{ 'struct': 'ObjectPropertyInfo',
-  'data': { 'name': 'str', 'type': 'str' } }
-
-##
-# @qom-list:
-#
-# This command will list any properties of a object given a path in the object
-# model.
-#
-# @path: the path within the object model.  See @qom-get for a description of
-#        this parameter.
-#
-# Returns: a list of @ObjectPropertyInfo that describe the properties of the
-#          object.
-#
-# Since: 1.2
-##
-{ 'command': 'qom-list',
-  'data': { 'path': 'str' },
-  'returns': [ 'ObjectPropertyInfo' ] }
-
-##
-# @qom-get:
-#
-# This command will get a property from a object model path and return the
-# value.
-#
-# @path: The path within the object model.  There are two forms of supported
-#        paths--absolute and partial paths.
-#
-#        Absolute paths are derived from the root object and can follow child<>
-#        or link<> properties.  Since they can follow link<> properties, they
-#        can be arbitrarily long.  Absolute paths look like absolute filenames
-#        and are prefixed  with a leading slash.
-#
-#        Partial paths look like relative filenames.  They do not begin
-#        with a prefix.  The matching rules for partial paths are subtle but
-#        designed to make specifying objects easy.  At each level of the
-#        composition tree, the partial path is matched as an absolute path.
-#        The first match is not returned.  At least two matches are searched
-#        for.  A successful result is only returned if only one match is
-#        found.  If more than one match is found, a flag is return to
-#        indicate that the match was ambiguous.
-#
-# @property: The property name to read
-#
-# Returns: The property value.  The type depends on the property
-#          type. child<> and link<> properties are returned as #str
-#          pathnames.  All integer property types (u8, u16, etc) are
-#          returned as #int.
-#
-# Since: 1.2
-##
-{ 'command': 'qom-get',
-  'data': { 'path': 'str', 'property': 'str' },
-  'returns': 'any' }
-
-##
-# @qom-set:
-#
-# This command will set a property from a object model path.
-#
-# @path: see @qom-get for a description of this parameter
-#
-# @property: the property name to set
-#
-# @value: a value who's type is appropriate for the property type.  See @qom-get
-#         for a description of type mapping.
-#
-# Since: 1.2
-##
-{ 'command': 'qom-set',
-  'data': { 'path': 'str', 'property': 'str', 'value': 'any' } }
-
-##
-# @change:
-#
-# This command is multiple commands multiplexed together.
-#
-# @device: This is normally the name of a block device but it may also be 'vnc'.
-#          when it's 'vnc', then sub command depends on @target
-#
-# @target: If @device is a block device, then this is the new filename.
-#          If @device is 'vnc', then if the value 'password' selects the vnc
-#          change password command.   Otherwise, this specifies a new server URI
-#          address to listen to for VNC connections.
-#
-# @arg:    If @device is a block device, then this is an optional format to open
-#          the device with.
-#          If @device is 'vnc' and @target is 'password', this is the new VNC
-#          password to set.  See change-vnc-password for additional notes.
-#
-# Returns: Nothing on success.
-#          If @device is not a valid block device, DeviceNotFound
-#
-# Notes:  This interface is deprecated, and it is strongly recommended that you
-#         avoid using it.  For changing block devices, use
-#         blockdev-change-medium; for changing VNC parameters, use
-#         change-vnc-password.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# 1. Change a removable medium
-#
-# -> { "execute": "change",
-#      "arguments": { "device": "ide1-cd0",
-#                     "target": "/srv/images/Fedora-12-x86_64-DVD.iso" } }
-# <- { "return": {} }
-#
-# 2. Change VNC password
-#
-# -> { "execute": "change",
-#      "arguments": { "device": "vnc", "target": "password",
-#                     "arg": "foobar1" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'change',
-  'data': {'device': 'str', 'target': 'str', '*arg': 'str'} }
-
-##
-# @ObjectTypeInfo:
-#
-# This structure describes a search result from @qom-list-types
-#
-# @name: the type name found in the search
-#
-# @abstract: the type is abstract and can't be directly instantiated.
-#            Omitted if false. (since 2.10)
-#
-# @parent: Name of parent type, if any (since 2.10)
-#
-# Since: 1.1
-##
-{ 'struct': 'ObjectTypeInfo',
-  'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } }
-
-##
-# @qom-list-types:
-#
-# This command will return a list of types given search parameters
-#
-# @implements: if specified, only return types that implement this type name
-#
-# @abstract: if true, include abstract types in the results
-#
-# Returns: a list of @ObjectTypeInfo or an empty list if no results are found
-#
-# Since: 1.1
-##
-{ 'command': 'qom-list-types',
-  'data': { '*implements': 'str', '*abstract': 'bool' },
-  'returns': [ 'ObjectTypeInfo' ] }
-
-##
-# @DevicePropertyInfo:
-#
-# Information about device properties.
-#
-# @name: the name of the property
-# @type: the typename of the property
-# @description: if specified, the description of the property.
-#               (since 2.2)
-#
-# Since: 1.2
-##
-{ 'struct': 'DevicePropertyInfo',
-  'data': { 'name': 'str', 'type': 'str', '*description': 'str' } }
-
-##
-# @device-list-properties:
-#
-# List properties associated with a device.
-#
-# @typename: the type name of a device
-#
-# Returns: a list of DevicePropertyInfo describing a devices properties
-#
-# Since: 1.2
-##
-{ 'command': 'device-list-properties',
-  'data': { 'typename': 'str'},
-  'returns': [ 'DevicePropertyInfo' ] }
-
-##
-# @xen-set-global-dirty-log:
-#
-# Enable or disable the global dirty log mode.
-#
-# @enable: true to enable, false to disable.
-#
-# Returns: nothing
-#
-# Since: 1.3
-#
-# Example:
-#
-# -> { "execute": "xen-set-global-dirty-log",
-#      "arguments": { "enable": true } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }
-
-##
-# @device_add:
-#
-# @driver: the name of the new device's driver
-#
-# @bus: the device's parent bus (device tree path)
-#
-# @id: the device's ID, must be unique
-#
-# Additional arguments depend on the type.
-#
-# Add a device.
-#
-# Notes:
-# 1. For detailed information about this command, please refer to the
-#    'docs/qdev-device-use.txt' file.
-#
-# 2. It's possible to list device properties by running QEMU with the
-#    "-device DEVICE,help" command-line argument, where DEVICE is the
-#    device's name
-#
-# Example:
-#
-# -> { "execute": "device_add",
-#      "arguments": { "driver": "e1000", "id": "net1",
-#                     "bus": "pci.0",
-#                     "mac": "52:54:00:12:34:56" } }
-# <- { "return": {} }
-#
-# TODO: This command effectively bypasses QAPI completely due to its
-# "additional arguments" business.  It shouldn't have been added to
-# the schema in this form.  It should be qapified properly, or
-# replaced by a properly qapified command.
-#
-# Since: 0.13
-##
-{ 'command': 'device_add',
-  'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
-  'gen': false } # so we can get the additional arguments
-
-##
-# @device_del:
-#
-# Remove a device from a guest
-#
-# @id: the device's ID or QOM path
-#
-# Returns: Nothing on success
-#          If @id is not a valid device, DeviceNotFound
-#
-# Notes: When this command completes, the device may not be removed from the
-#        guest.  Hot removal is an operation that requires guest cooperation.
-#        This command merely requests that the guest begin the hot removal
-#        process.  Completion of the device removal process is signaled with a
-#        DEVICE_DELETED event. Guest reset will automatically complete removal
-#        for all devices.
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "device_del",
-#      "arguments": { "id": "net1" } }
-# <- { "return": {} }
-#
-# -> { "execute": "device_del",
-#      "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'device_del', 'data': {'id': 'str'} }
-
-##
-# @DEVICE_DELETED:
-#
-# Emitted whenever the device removal completion is acknowledged by the guest.
-# At this point, it's safe to reuse the specified device ID. Device removal can
-# be initiated by the guest or by HMP/QMP commands.
-#
-# @device: device name
-#
-# @path: device path
-#
-# Since: 1.5
-#
-# Example:
-#
-# <- { "event": "DEVICE_DELETED",
-#      "data": { "device": "virtio-net-pci-0",
-#                "path": "/machine/peripheral/virtio-net-pci-0" },
-#      "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-#
-##
-{ 'event': 'DEVICE_DELETED',
-  'data': { '*device': 'str', 'path': 'str' } }
-
-##
-# @DumpGuestMemoryFormat:
-#
-# An enumeration of guest-memory-dump's format.
-#
-# @elf: elf format
-#
-# @kdump-zlib: kdump-compressed format with zlib-compressed
-#
-# @kdump-lzo: kdump-compressed format with lzo-compressed
-#
-# @kdump-snappy: kdump-compressed format with snappy-compressed
-#
-# Since: 2.0
-##
-{ 'enum': 'DumpGuestMemoryFormat',
-  'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
-
-##
-# @dump-guest-memory:
-#
-# Dump guest's memory to vmcore. It is a synchronous operation that can take
-# very long depending on the amount of guest memory.
-#
-# @paging: if true, do paging to get guest's memory mapping. This allows
-#          using gdb to process the core file.
-#
-#          IMPORTANT: this option can make QEMU allocate several gigabytes
-#                     of RAM. This can happen for a large guest, or a
-#                     malicious guest pretending to be large.
-#
-#          Also, paging=true has the following limitations:
-#
-#             1. The guest may be in a catastrophic state or can have corrupted
-#                memory, which cannot be trusted
-#             2. The guest can be in real-mode even if paging is enabled. For
-#                example, the guest uses ACPI to sleep, and ACPI sleep state
-#                goes in real-mode
-#             3. Currently only supported on i386 and x86_64.
-#
-# @protocol: the filename or file descriptor of the vmcore. The supported
-#            protocols are:
-#
-#            1. file: the protocol starts with "file:", and the following
-#               string is the file's path.
-#            2. fd: the protocol starts with "fd:", and the following string
-#               is the fd's name.
-#
-# @detach: if true, QMP will return immediately rather than
-#          waiting for the dump to finish. The user can track progress
-#          using "query-dump". (since 2.6).
-#
-# @begin: if specified, the starting physical address.
-#
-# @length: if specified, the memory size, in bytes. If you don't
-#          want to dump all guest's memory, please specify the start @begin
-#          and @length
-#
-# @format: if specified, the format of guest memory dump. But non-elf
-#          format is conflict with paging and filter, ie. @paging, @begin and
-#          @length is not allowed to be specified with non-elf @format at the
-#          same time (since 2.0)
-#
-# Note: All boolean arguments default to false
-#
-# Returns: nothing on success
-#
-# Since: 1.2
-#
-# Example:
-#
-# -> { "execute": "dump-guest-memory",
-#      "arguments": { "protocol": "fd:dump" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'dump-guest-memory',
-  'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
-            '*begin': 'int', '*length': 'int',
-            '*format': 'DumpGuestMemoryFormat'} }
-
-##
-# @DumpStatus:
-#
-# Describe the status of a long-running background guest memory dump.
-#
-# @none: no dump-guest-memory has started yet.
-#
-# @active: there is one dump running in background.
-#
-# @completed: the last dump has finished successfully.
-#
-# @failed: the last dump has failed.
-#
-# Since: 2.6
-##
-{ 'enum': 'DumpStatus',
-  'data': [ 'none', 'active', 'completed', 'failed' ] }
-
-##
-# @DumpQueryResult:
-#
-# The result format for 'query-dump'.
-#
-# @status: enum of @DumpStatus, which shows current dump status
-#
-# @completed: bytes written in latest dump (uncompressed)
-#
-# @total: total bytes to be written in latest dump (uncompressed)
-#
-# Since: 2.6
-##
-{ 'struct': 'DumpQueryResult',
-  'data': { 'status': 'DumpStatus',
-            'completed': 'int',
-            'total': 'int' } }
-
-##
-# @query-dump:
-#
-# Query latest dump status.
-#
-# Returns: A @DumpStatus object showing the dump status.
-#
-# Since: 2.6
-#
-# Example:
-#
-# -> { "execute": "query-dump" }
-# <- { "return": { "status": "active", "completed": 1024000,
-#                  "total": 2048000 } }
-#
-##
-{ 'command': 'query-dump', 'returns': 'DumpQueryResult' }
-
-##
-# @DUMP_COMPLETED:
-#
-# Emitted when background dump has completed
-#
-# @result: DumpQueryResult type described in qapi-schema.json.
-#
-# @error: human-readable error string that provides
-#         hint on why dump failed. Only presents on failure. The
-#         user should not try to interpret the error string.
-#
-# Since: 2.6
-#
-# Example:
-#
-# { "event": "DUMP_COMPLETED",
-#   "data": {"result": {"total": 1090650112, "status": "completed",
-#                       "completed": 1090650112} } }
-#
-##
-{ 'event': 'DUMP_COMPLETED' ,
-  'data': { 'result': 'DumpQueryResult', '*error': 'str' } }
-
-##
-# @DumpGuestMemoryCapability:
-#
-# A list of the available formats for dump-guest-memory
-#
-# Since: 2.0
-##
-{ 'struct': 'DumpGuestMemoryCapability',
-  'data': {
-      'formats': ['DumpGuestMemoryFormat'] } }
-
-##
-# @query-dump-guest-memory-capability:
-#
-# Returns the available formats for dump-guest-memory
-#
-# Returns:  A @DumpGuestMemoryCapability object listing available formats for
-#           dump-guest-memory
-#
-# Since: 2.0
-#
-# Example:
-#
-# -> { "execute": "query-dump-guest-memory-capability" }
-# <- { "return": { "formats":
-#                  ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] }
-#
-##
-{ 'command': 'query-dump-guest-memory-capability',
-  'returns': 'DumpGuestMemoryCapability' }
-
-##
-# @dump-skeys:
-#
-# Dump guest's storage keys
-#
-# @filename: the path to the file to dump to
-#
-# This command is only supported on s390 architecture.
-#
-# Since: 2.5
-#
-# Example:
-#
-# -> { "execute": "dump-skeys",
-#      "arguments": { "filename": "/tmp/skeys" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'dump-skeys',
-  'data': { 'filename': 'str' } }
-
-##
-# @object-add:
-#
-# Create a QOM object.
-#
-# @qom-type: the class name for the object to be created
-#
-# @id: the name of the new object
-#
-# @props: a dictionary of properties to be passed to the backend
-#
-# Returns: Nothing on success
-#          Error if @qom-type is not a valid class name
-#
-# Since: 2.0
-#
-# Example:
-#
-# -> { "execute": "object-add",
-#      "arguments": { "qom-type": "rng-random", "id": "rng1",
-#                     "props": { "filename": "/dev/hwrng" } } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'object-add',
-  'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} }
-
-##
-# @object-del:
-#
-# Remove a QOM object.
-#
-# @id: the name of the QOM object to remove
-#
-# Returns: Nothing on success
-#          Error if @id is not a valid id for a QOM object
-#
-# Since: 2.0
-#
-# Example:
-#
-# -> { "execute": "object-del", "arguments": { "id": "rng1" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'object-del', 'data': {'id': 'str'} }
-
-##
-# @getfd:
-#
-# Receive a file descriptor via SCM rights and assign it a name
-#
-# @fdname: file descriptor name
-#
-# Returns: Nothing on success
-#
-# Since: 0.14.0
-#
-# Notes: If @fdname already exists, the file descriptor assigned to
-#        it will be closed and replaced by the received file
-#        descriptor.
-#
-#        The 'closefd' command can be used to explicitly close the
-#        file descriptor when it is no longer needed.
-#
-# Example:
-#
-# -> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'getfd', 'data': {'fdname': 'str'} }
-
-##
-# @closefd:
-#
-# Close a file descriptor previously passed via SCM rights
-#
-# @fdname: file descriptor name
-#
-# Returns: Nothing on success
-#
-# Since: 0.14.0
-#
-# Example:
-#
-# -> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'closefd', 'data': {'fdname': 'str'} }
-
-##
-# @MachineInfo:
-#
-# Information describing a machine.
-#
-# @name: the name of the machine
-#
-# @alias: an alias for the machine name
-#
-# @is-default: whether the machine is default
-#
-# @cpu-max: maximum number of CPUs supported by the machine type
-#           (since 1.5.0)
-#
-# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7.0)
-#
-# Since: 1.2.0
-##
-{ 'struct': 'MachineInfo',
-  'data': { 'name': 'str', '*alias': 'str',
-            '*is-default': 'bool', 'cpu-max': 'int',
-            'hotpluggable-cpus': 'bool'} }
-
-##
-# @query-machines:
-#
-# Return a list of supported machines
-#
-# Returns: a list of MachineInfo
-#
-# Since: 1.2.0
-##
-{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
-
-##
-# @CpuDefinitionInfo:
-#
-# Virtual CPU definition.
-#
-# @name: the name of the CPU definition
-#
-# @migration-safe: whether a CPU definition can be safely used for
-#                  migration in combination with a QEMU compatibility machine
-#                  when migrating between different QMU versions and between
-#                  hosts with different sets of (hardware or software)
-#                  capabilities. If not provided, information is not available
-#                  and callers should not assume the CPU definition to be
-#                  migration-safe. (since 2.8)
-#
-# @static: whether a CPU definition is static and will not change depending on
-#          QEMU version, machine type, machine options and accelerator options.
-#          A static model is always migration-safe. (since 2.8)
-#
-# @unavailable-features: List of properties that prevent
-#                        the CPU model from running in the current
-#                        host. (since 2.8)
-# @typename: Type name that can be used as argument to @device-list-properties,
-#            to introspect properties configurable using -cpu or -global.
-#            (since 2.9)
-#
-# @unavailable-features is a list of QOM property names that
-# represent CPU model attributes that prevent the CPU from running.
-# If the QOM property is read-only, that means there's no known
-# way to make the CPU model run in the current host. Implementations
-# that choose not to provide specific information return the
-# property name "type".
-# If the property is read-write, it means that it MAY be possible
-# to run the CPU model in the current host if that property is
-# changed. Management software can use it as hints to suggest or
-# choose an alternative for the user, or just to generate meaningful
-# error messages explaining why the CPU model can't be used.
-# If @unavailable-features is an empty list, the CPU model is
-# runnable using the current host and machine-type.
-# If @unavailable-features is not present, runnability
-# information for the CPU is not available.
-#
-# Since: 1.2.0
-##
-{ 'struct': 'CpuDefinitionInfo',
-  'data': { 'name': 'str', '*migration-safe': 'bool', 'static': 'bool',
-            '*unavailable-features': [ 'str' ], 'typename': 'str' } }
-
-##
-# @MemoryInfo:
-#
-# Actual memory information in bytes.
-#
-# @base-memory: size of "base" memory specified with command line
-#               option -m.
-#
-# @plugged-memory: size of memory that can be hot-unplugged. This field
-#                  is omitted if target doesn't support memory hotplug
-#                  (i.e. CONFIG_MEM_HOTPLUG not defined on build time).
-#
-# Since: 2.11.0
-##
-{ 'struct': 'MemoryInfo',
-  'data'  : { 'base-memory': 'size', '*plugged-memory': 'size' } }
-
-##
-# @query-memory-size-summary:
-#
-# Return the amount of initially allocated and present hotpluggable (if
-# enabled) memory in bytes.
-#
-# Example:
-#
-# -> { "execute": "query-memory-size-summary" }
-# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } }
-#
-# Since: 2.11.0
-##
-{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' }
-
-##
-# @query-cpu-definitions:
-#
-# Return a list of supported virtual CPU definitions
-#
-# Returns: a list of CpuDefInfo
-#
-# Since: 1.2.0
-##
-{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
-
-##
-# @CpuModelInfo:
-#
-# Virtual CPU model.
-#
-# A CPU model consists of the name of a CPU definition, to which
-# delta changes are applied (e.g. features added/removed). Most magic values
-# that an architecture might require should be hidden behind the name.
-# However, if required, architectures can expose relevant properties.
-#
-# @name: the name of the CPU definition the model is based on
-# @props: a dictionary of QOM properties to be applied
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelInfo',
-  'data': { 'name': 'str',
-            '*props': 'any' } }
-
-##
-# @CpuModelExpansionType:
-#
-# An enumeration of CPU model expansion types.
-#
-# @static: Expand to a static CPU model, a combination of a static base
-#          model name and property delta changes. As the static base model will
-#          never change, the expanded CPU model will be the same, independant of
-#          independent of QEMU version, machine type, machine options, and
-#          accelerator options. Therefore, the resulting model can be used by
-#          tooling without having to specify a compatibility machine - e.g. when
-#          displaying the "host" model. static CPU models are migration-safe.
-#
-# @full: Expand all properties. The produced model is not guaranteed to be
-#        migration-safe, but allows tooling to get an insight and work with
-#        model details.
-#
-# Note: When a non-migration-safe CPU model is expanded in static mode, some
-# features enabled by the CPU model may be omitted, because they can't be
-# implemented by a static CPU model definition (e.g. cache info passthrough and
-# PMU passthrough in x86). If you need an accurate representation of the
-# features enabled by a non-migration-safe CPU model, use @full. If you need a
-# static representation that will keep ABI compatibility even when changing QEMU
-# version or machine-type, use @static (but keep in mind that some features may
-# be omitted).
-#
-# Since: 2.8.0
-##
-{ 'enum': 'CpuModelExpansionType',
-  'data': [ 'static', 'full' ] }
-
-
-##
-# @CpuModelExpansionInfo:
-#
-# The result of a cpu model expansion.
-#
-# @model: the expanded CpuModelInfo.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelExpansionInfo',
-  'data': { 'model': 'CpuModelInfo' } }
-
-
-##
-# @query-cpu-model-expansion:
-#
-# Expands a given CPU model (or a combination of CPU model + additional options)
-# to different granularities, allowing tooling to get an understanding what a
-# specific CPU model looks like in QEMU under a certain configuration.
-#
-# This interface can be used to query the "host" CPU model.
-#
-# The data returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model  may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support all expansion types. s390x supports
-# "full" and "static".
-#
-# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
-#          not supported, if the model cannot be expanded, if the model contains
-#          an unknown CPU definition name, unknown properties or properties
-#          with a wrong type. Also returns an error if an expansion type is
-#          not supported.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-expansion',
-  'data': { 'type': 'CpuModelExpansionType',
-            'model': 'CpuModelInfo' },
-  'returns': 'CpuModelExpansionInfo' }
-
-##
-# @CpuModelCompareResult:
-#
-# An enumeration of CPU model comparation results. The result is usually
-# calculated using e.g. CPU features or CPU generations.
-#
-# @incompatible: If model A is incompatible to model B, model A is not
-#                guaranteed to run where model B runs and the other way around.
-#
-# @identical: If model A is identical to model B, model A is guaranteed to run
-#             where model B runs and the other way around.
-#
-# @superset: If model A is a superset of model B, model B is guaranteed to run
-#            where model A runs. There are no guarantees about the other way.
-#
-# @subset: If model A is a subset of model B, model A is guaranteed to run
-#          where model B runs. There are no guarantees about the other way.
-#
-# Since: 2.8.0
-##
-{ 'enum': 'CpuModelCompareResult',
-  'data': [ 'incompatible', 'identical', 'superset', 'subset' ] }
-
-##
-# @CpuModelCompareInfo:
-#
-# The result of a CPU model comparison.
-#
-# @result: The result of the compare operation.
-# @responsible-properties: List of properties that led to the comparison result
-#                          not being identical.
-#
-# @responsible-properties is a list of QOM property names that led to
-# both CPUs not being detected as identical. For identical models, this
-# list is empty.
-# If a QOM property is read-only, that means there's no known way to make the
-# CPU models identical. If the special property name "type" is included, the
-# models are by definition not identical and cannot be made identical.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelCompareInfo',
-  'data': {'result': 'CpuModelCompareResult',
-           'responsible-properties': ['str']
-          }
-}
-
-##
-# @query-cpu-model-comparison:
-#
-# Compares two CPU models, returning how they compare in a specific
-# configuration. The results indicates how both models compare regarding
-# runnability. This result can be used by tooling to make decisions if a
-# certain CPU model will run in a certain configuration or if a compatible
-# CPU model has to be created by baselining.
-#
-# Usually, a CPU model is compared against the maximum possible CPU model
-# of a certain configuration (e.g. the "host" model for KVM). If that CPU
-# model is identical or a subset, it will run in that configuration.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support comparing CPU models. s390x supports
-# comparing CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
-#          not supported, if a model cannot be used, if a model contains
-#          an unknown cpu definition name, unknown properties or properties
-#          with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-comparison',
-  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelCompareInfo' }
-
-##
-# @CpuModelBaselineInfo:
-#
-# The result of a CPU model baseline.
-#
-# @model: the baselined CpuModelInfo.
-#
-# Since: 2.8.0
-##
-{ 'struct': 'CpuModelBaselineInfo',
-  'data': { 'model': 'CpuModelInfo' } }
-
-##
-# @query-cpu-model-baseline:
-#
-# Baseline two CPU models, creating a compatible third model. The created
-# model will always be a static, migration-safe CPU model (see "static"
-# CPU model expansion for details).
-#
-# This interface can be used by tooling to create a compatible CPU model out
-# two CPU models. The created CPU model will be identical to or a subset of
-# both CPU models when comparing them. Therefore, the created CPU model is
-# guaranteed to run where the given CPU models run.
-#
-# The result returned by this command may be affected by:
-#
-# * QEMU version: CPU models may look different depending on the QEMU version.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine-type: CPU model may look different depending on the machine-type.
-#   (Except for CPU models reported as "static" in query-cpu-definitions.)
-# * machine options (including accelerator): in some architectures, CPU models
-#   may look different depending on machine and accelerator options. (Except for
-#   CPU models reported as "static" in query-cpu-definitions.)
-# * "-cpu" arguments and global properties: arguments to the -cpu option and
-#   global properties may affect expansion of CPU models. Using
-#   query-cpu-model-expansion while using these is not advised.
-#
-# Some architectures may not support baselining CPU models. s390x supports
-# baselining CPU models.
-#
-# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
-#          not supported, if a model cannot be used, if a model contains
-#          an unknown cpu definition name, unknown properties or properties
-#          with wrong types.
-#
-# Since: 2.8.0
-##
-{ 'command': 'query-cpu-model-baseline',
-  'data': { 'modela': 'CpuModelInfo',
-            'modelb': 'CpuModelInfo' },
-  'returns': 'CpuModelBaselineInfo' }
-
-##
-# @AddfdInfo:
-#
-# Information about a file descriptor that was added to an fd set.
-#
-# @fdset-id: The ID of the fd set that @fd was added to.
-#
-# @fd: The file descriptor that was received via SCM rights and
-#      added to the fd set.
-#
-# Since: 1.2.0
-##
-{ 'struct': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }
-
-##
-# @add-fd:
-#
-# Add a file descriptor, that was passed via SCM rights, to an fd set.
-#
-# @fdset-id: The ID of the fd set to add the file descriptor to.
-#
-# @opaque: A free-form string that can be used to describe the fd.
-#
-# Returns: @AddfdInfo on success
-#
-#          If file descriptor was not received, FdNotSupplied
-#
-#          If @fdset-id is a negative value, InvalidParameterValue
-#
-# Notes: The list of fd sets is shared by all monitor connections.
-#
-#        If @fdset-id is not specified, a new fd set will be created.
-#
-# Since: 1.2.0
-#
-# Example:
-#
-# -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } }
-# <- { "return": { "fdset-id": 1, "fd": 3 } }
-#
-##
-{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
-  'returns': 'AddfdInfo' }
-
-##
-# @remove-fd:
-#
-# Remove a file descriptor from an fd set.
-#
-# @fdset-id: The ID of the fd set that the file descriptor belongs to.
-#
-# @fd: The file descriptor that is to be removed.
-#
-# Returns: Nothing on success
-#          If @fdset-id or @fd is not found, FdNotFound
-#
-# Since: 1.2.0
-#
-# Notes: The list of fd sets is shared by all monitor connections.
-#
-#        If @fd is not specified, all file descriptors in @fdset-id
-#        will be removed.
-#
-# Example:
-#
-# -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }
-
-##
-# @FdsetFdInfo:
-#
-# Information about a file descriptor that belongs to an fd set.
-#
-# @fd: The file descriptor value.
-#
-# @opaque: A free-form string that can be used to describe the fd.
-#
-# Since: 1.2.0
-##
-{ 'struct': 'FdsetFdInfo',
-  'data': {'fd': 'int', '*opaque': 'str'} }
-
-##
-# @FdsetInfo:
-#
-# Information about an fd set.
-#
-# @fdset-id: The ID of the fd set.
-#
-# @fds: A list of file descriptors that belong to this fd set.
-#
-# Since: 1.2.0
-##
-{ 'struct': 'FdsetInfo',
-  'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }
-
-##
-# @query-fdsets:
-#
-# Return information describing all fd sets.
-#
-# Returns: A list of @FdsetInfo
-#
-# Since: 1.2.0
-#
-# Note: The list of fd sets is shared by all monitor connections.
-#
-# Example:
-#
-# -> { "execute": "query-fdsets" }
-# <- { "return": [
-#        {
-#          "fds": [
-#            {
-#              "fd": 30,
-#              "opaque": "rdonly:/path/to/file"
-#            },
-#            {
-#              "fd": 24,
-#              "opaque": "rdwr:/path/to/file"
-#            }
-#          ],
-#          "fdset-id": 1
-#        },
-#        {
-#          "fds": [
-#            {
-#              "fd": 28
-#            },
-#            {
-#              "fd": 29
-#            }
-#          ],
-#          "fdset-id": 0
-#        }
-#      ]
-#    }
-#
-##
-{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
-
-##
-# @TargetInfo:
-#
-# Information describing the QEMU target.
-#
-# @arch: the target architecture (eg "x86_64", "i386", etc)
-#
-# Since: 1.2.0
-##
-{ 'struct': 'TargetInfo',
-  'data': { 'arch': 'str' } }
-
-##
-# @query-target:
-#
-# Return information about the target for this QEMU
-#
-# Returns: TargetInfo
-#
-# Since: 1.2.0
-##
-{ 'command': 'query-target', 'returns': 'TargetInfo' }
-
-##
-# @AcpiTableOptions:
-#
-# Specify an ACPI table on the command line to load.
-#
-# At most one of @file and @data can be specified. The list of files specified
-# by any one of them is loaded and concatenated in order. If both are omitted,
-# @data is implied.
-#
-# Other fields / optargs can be used to override fields of the generic ACPI
-# table header; refer to the ACPI specification 5.0, section 5.2.6 System
-# Description Table Header. If a header field is not overridden, then the
-# corresponding value from the concatenated blob is used (in case of @file), or
-# it is filled in with a hard-coded value (in case of @data).
-#
-# String fields are copied into the matching ACPI member from lowest address
-# upwards, and silently truncated / NUL-padded to length.
-#
-# @sig: table signature / identifier (4 bytes)
-#
-# @rev: table revision number (dependent on signature, 1 byte)
-#
-# @oem_id: OEM identifier (6 bytes)
-#
-# @oem_table_id: OEM table identifier (8 bytes)
-#
-# @oem_rev: OEM-supplied revision number (4 bytes)
-#
-# @asl_compiler_id: identifier of the utility that created the table
-#                   (4 bytes)
-#
-# @asl_compiler_rev: revision number of the utility that created the
-#                    table (4 bytes)
-#
-# @file: colon (:) separated list of pathnames to load and
-#        concatenate as table data. The resultant binary blob is expected to
-#        have an ACPI table header. At least one file is required. This field
-#        excludes @data.
-#
-# @data: colon (:) separated list of pathnames to load and
-#        concatenate as table data. The resultant binary blob must not have an
-#        ACPI table header. At least one file is required. This field excludes
-#        @file.
-#
-# Since: 1.5
-##
-{ 'struct': 'AcpiTableOptions',
-  'data': {
-    '*sig':               'str',
-    '*rev':               'uint8',
-    '*oem_id':            'str',
-    '*oem_table_id':      'str',
-    '*oem_rev':           'uint32',
-    '*asl_compiler_id':   'str',
-    '*asl_compiler_rev':  'uint32',
-    '*file':              'str',
-    '*data':              'str' }}
-
-##
-# @CommandLineParameterType:
-#
-# Possible types for an option parameter.
-#
-# @string: accepts a character string
-#
-# @boolean: accepts "on" or "off"
-#
-# @number: accepts a number
-#
-# @size: accepts a number followed by an optional suffix (K)ilo,
-#        (M)ega, (G)iga, (T)era
-#
-# Since: 1.5
-##
-{ 'enum': 'CommandLineParameterType',
-  'data': ['string', 'boolean', 'number', 'size'] }
-
-##
-# @CommandLineParameterInfo:
-#
-# Details about a single parameter of a command line option.
-#
-# @name: parameter name
-#
-# @type: parameter @CommandLineParameterType
-#
-# @help: human readable text string, not suitable for parsing.
-#
-# @default: default value string (since 2.1)
-#
-# Since: 1.5
-##
-{ 'struct': 'CommandLineParameterInfo',
-  'data': { 'name': 'str',
-            'type': 'CommandLineParameterType',
-            '*help': 'str',
-            '*default': 'str' } }
-
-##
-# @CommandLineOptionInfo:
-#
-# Details about a command line option, including its list of parameter details
-#
-# @option: option name
-#
-# @parameters: an array of @CommandLineParameterInfo
-#
-# Since: 1.5
-##
-{ 'struct': 'CommandLineOptionInfo',
-  'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }
-
-##
-# @query-command-line-options:
-#
-# Query command line option schema.
-#
-# @option: option name
-#
-# Returns: list of @CommandLineOptionInfo for all options (or for the given
-#          @option).  Returns an error if the given @option doesn't exist.
-#
-# Since: 1.5
-#
-# Example:
-#
-# -> { "execute": "query-command-line-options",
-#      "arguments": { "option": "option-rom" } }
-# <- { "return": [
-#         {
-#             "parameters": [
-#                 {
-#                     "name": "romfile",
-#                     "type": "string"
-#                 },
-#                 {
-#                     "name": "bootindex",
-#                     "type": "number"
-#                 }
-#             ],
-#             "option": "option-rom"
-#         }
-#      ]
-#    }
-#
-##
-{'command': 'query-command-line-options', 'data': { '*option': 'str' },
- 'returns': ['CommandLineOptionInfo'] }
-
-##
-# @X86CPURegister32:
-#
-# A X86 32-bit register
-#
-# Since: 1.5
-##
-{ 'enum': 'X86CPURegister32',
-  'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }
-
-##
-# @X86CPUFeatureWordInfo:
-#
-# Information about a X86 CPU feature word
-#
-# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word
-#
-# @cpuid-input-ecx: Input ECX value for CPUID instruction for that
-#                   feature word
-#
-# @cpuid-register: Output register containing the feature bits
-#
-# @features: value of output register, containing the feature bits
-#
-# Since: 1.5
-##
-{ 'struct': 'X86CPUFeatureWordInfo',
-  'data': { 'cpuid-input-eax': 'int',
-            '*cpuid-input-ecx': 'int',
-            'cpuid-register': 'X86CPURegister32',
-            'features': 'int' } }
-
-##
-# @DummyForceArrays:
-#
-# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally
-#
-# Since: 2.5
-##
-{ 'struct': 'DummyForceArrays',
-  'data': { 'unused': ['X86CPUFeatureWordInfo'] } }
-
-
-##
-# @NumaOptionsType:
-#
-# @node: NUMA nodes configuration
-#
-# @dist: NUMA distance configuration (since 2.10)
-#
-# @cpu: property based CPU(s) to node mapping (Since: 2.10)
-#
-# Since: 2.1
-##
-{ 'enum': 'NumaOptionsType',
-  'data': [ 'node', 'dist', 'cpu' ] }
-
-##
-# @NumaOptions:
-#
-# A discriminated record of NUMA options. (for OptsVisitor)
-#
-# Since: 2.1
-##
-{ 'union': 'NumaOptions',
-  'base': { 'type': 'NumaOptionsType' },
-  'discriminator': 'type',
-  'data': {
-    'node': 'NumaNodeOptions',
-    'dist': 'NumaDistOptions',
-    'cpu': 'NumaCpuOptions' }}
-
-##
-# @NumaNodeOptions:
-#
-# Create a guest NUMA node. (for OptsVisitor)
-#
-# @nodeid: NUMA node ID (increase by 1 from 0 if omitted)
-#
-# @cpus: VCPUs belonging to this node (assign VCPUS round-robin
-#         if omitted)
-#
-# @mem: memory size of this node; mutually exclusive with @memdev.
-#       Equally divide total memory among nodes if both @mem and @memdev are
-#       omitted.
-#
-# @memdev: memory backend object.  If specified for one node,
-#          it must be specified for all nodes.
-#
-# Since: 2.1
-##
-{ 'struct': 'NumaNodeOptions',
-  'data': {
-   '*nodeid': 'uint16',
-   '*cpus':   ['uint16'],
-   '*mem':    'size',
-   '*memdev': 'str' }}
-
-##
-# @NumaDistOptions:
-#
-# Set the distance between 2 NUMA nodes.
-#
-# @src: source NUMA node.
-#
-# @dst: destination NUMA node.
-#
-# @val: NUMA distance from source node to destination node.
-#       When a node is unreachable from another node, set the distance
-#       between them to 255.
-#
-# Since: 2.10
-##
-{ 'struct': 'NumaDistOptions',
-  'data': {
-   'src': 'uint16',
-   'dst': 'uint16',
-   'val': 'uint8' }}
-
-##
-# @NumaCpuOptions:
-#
-# Option "-numa cpu" overrides default cpu to node mapping.
-# It accepts the same set of cpu properties as returned by
-# query-hotpluggable-cpus[].props, where node-id could be used to
-# override default node mapping.
-#
-# Since: 2.10
-##
-{ 'struct': 'NumaCpuOptions',
-   'base': 'CpuInstanceProperties',
-   'data' : {} }
-
-##
-# @HostMemPolicy:
-#
-# Host memory policy types
-#
-# @default: restore default policy, remove any nondefault policy
-#
-# @preferred: set the preferred host nodes for allocation
-#
-# @bind: a strict policy that restricts memory allocation to the
-#        host nodes specified
-#
-# @interleave: memory allocations are interleaved across the set
-#              of host nodes specified
-#
-# Since: 2.1
-##
-{ 'enum': 'HostMemPolicy',
-  'data': [ 'default', 'preferred', 'bind', 'interleave' ] }
-
-##
-# @Memdev:
-#
-# Information about memory backend
-#
-# @id: backend's ID if backend has 'id' property (since 2.9)
-#
-# @size: memory backend size
-#
-# @merge: enables or disables memory merge support
-#
-# @dump: includes memory backend's memory in a core dump or not
-#
-# @prealloc: enables or disables memory preallocation
-#
-# @host-nodes: host nodes for its memory policy
-#
-# @policy: memory policy of memory backend
-#
-# Since: 2.1
-##
-{ 'struct': 'Memdev',
-  'data': {
-    '*id':        'str',
-    'size':       'size',
-    'merge':      'bool',
-    'dump':       'bool',
-    'prealloc':   'bool',
-    'host-nodes': ['uint16'],
-    'policy':     'HostMemPolicy' }}
-
-##
-# @query-memdev:
-#
-# Returns information for all memory backends.
-#
-# Returns: a list of @Memdev.
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "query-memdev" }
-# <- { "return": [
-#        {
-#          "id": "mem1",
-#          "size": 536870912,
-#          "merge": false,
-#          "dump": true,
-#          "prealloc": false,
-#          "host-nodes": [0, 1],
-#          "policy": "bind"
-#        },
-#        {
-#          "size": 536870912,
-#          "merge": false,
-#          "dump": true,
-#          "prealloc": true,
-#          "host-nodes": [2, 3],
-#          "policy": "preferred"
-#        }
-#      ]
-#    }
-#
-##
-{ 'command': 'query-memdev', 'returns': ['Memdev'] }
-
-##
-# @PCDIMMDeviceInfo:
-#
-# PCDIMMDevice state information
-#
-# @id: device's ID
-#
-# @addr: physical address, where device is mapped
-#
-# @size: size of memory that the device provides
-#
-# @slot: slot number at which device is plugged in
-#
-# @node: NUMA node number where device is plugged in
-#
-# @memdev: memory backend linked with device
-#
-# @hotplugged: true if device was hotplugged
-#
-# @hotpluggable: true if device if could be added/removed while machine is running
-#
-# Since: 2.1
-##
-{ 'struct': 'PCDIMMDeviceInfo',
-  'data': { '*id': 'str',
-            'addr': 'int',
-            'size': 'int',
-            'slot': 'int',
-            'node': 'int',
-            'memdev': 'str',
-            'hotplugged': 'bool',
-            'hotpluggable': 'bool'
-          }
-}
-
-##
-# @MemoryDeviceInfo:
-#
-# Union containing information about a memory device
-#
-# Since: 2.1
-##
-{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} }
-
-##
-# @query-memory-devices:
-#
-# Lists available memory devices and their state
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "query-memory-devices" }
-# <- { "return": [ { "data":
-#                       { "addr": 5368709120,
-#                         "hotpluggable": true,
-#                         "hotplugged": true,
-#                         "id": "d1",
-#                         "memdev": "/objects/memX",
-#                         "node": 0,
-#                         "size": 1073741824,
-#                         "slot": 0},
-#                    "type": "dimm"
-#                  } ] }
-#
-##
-{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] }
-
-##
-# @MEM_UNPLUG_ERROR:
-#
-# Emitted when memory hot unplug error occurs.
-#
-# @device: device name
-#
-# @msg: Informative message
-#
-# Since: 2.4
-#
-# Example:
-#
-# <- { "event": "MEM_UNPLUG_ERROR"
-#      "data": { "device": "dimm1",
-#                "msg": "acpi: device unplug for unsupported device"
-#      },
-#      "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
-#
-##
-{ 'event': 'MEM_UNPLUG_ERROR',
-  'data': { 'device': 'str', 'msg': 'str' } }
-
-##
-# @ACPISlotType:
-#
-# @DIMM: memory slot
-# @CPU: logical CPU slot (since 2.7)
-##
-{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] }
-
-##
-# @ACPIOSTInfo:
-#
-# OSPM Status Indication for a device
-# For description of possible values of @source and @status fields
-# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec.
-#
-# @device: device ID associated with slot
-#
-# @slot: slot ID, unique per slot of a given @slot-type
-#
-# @slot-type: type of the slot
-#
-# @source: an integer containing the source event
-#
-# @status: an integer containing the status code
-#
-# Since: 2.1
-##
-{ 'struct': 'ACPIOSTInfo',
-  'data'  : { '*device': 'str',
-              'slot': 'str',
-              'slot-type': 'ACPISlotType',
-              'source': 'int',
-              'status': 'int' } }
-
-##
-# @query-acpi-ospm-status:
-#
-# Return a list of ACPIOSTInfo for devices that support status
-# reporting via ACPI _OST method.
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "query-acpi-ospm-status" }
-# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0},
-#                  { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0},
-#                  { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0},
-#                  { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0}
-#    ]}
-#
-##
-{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] }
-
-##
-# @ACPI_DEVICE_OST:
-#
-# Emitted when guest executes ACPI _OST method.
-#
-# @info: ACPIOSTInfo type as described in qapi-schema.json
-#
-# Since: 2.1
-#
-# Example:
-#
-# <- { "event": "ACPI_DEVICE_OST",
-#      "data": { "device": "d1", "slot": "0",
-#                "slot-type": "DIMM", "source": 1, "status": 0 } }
-#
-##
-{ 'event': 'ACPI_DEVICE_OST',
-     'data': { 'info': 'ACPIOSTInfo' } }
-
-##
-# @rtc-reset-reinjection:
-#
-# This command will reset the RTC interrupt reinjection backlog.
-# Can be used if another mechanism to synchronize guest time
-# is in effect, for example QEMU guest agent's guest-set-time
-# command.
-#
-# Since: 2.1
-#
-# Example:
-#
-# -> { "execute": "rtc-reset-reinjection" }
-# <- { "return": {} }
-#
-##
-{ 'command': 'rtc-reset-reinjection' }
-
-##
-# @RTC_CHANGE:
-#
-# Emitted when the guest changes the RTC time.
-#
-# @offset: offset between base RTC clock (as specified by -rtc base), and
-#          new RTC clock value
-#
-# Note: This event is rate-limited.
-#
-# Since: 0.13.0
-#
-# Example:
-#
-# <-   { "event": "RTC_CHANGE",
-#        "data": { "offset": 78 },
-#        "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
-#
-##
-{ 'event': 'RTC_CHANGE',
-  'data': { 'offset': 'int' } }
-
-##
-# @ReplayMode:
-#
-# Mode of the replay subsystem.
-#
-# @none: normal execution mode. Replay or record are not enabled.
-#
-# @record: record mode. All non-deterministic data is written into the
-#          replay log.
-#
-# @play: replay mode. Non-deterministic data required for system execution
-#        is read from the log.
-#
-# Since: 2.5
-##
-{ 'enum': 'ReplayMode',
-  'data': [ 'none', 'record', 'play' ] }
-
-##
-# @xen-load-devices-state:
-#
-# Load the state of all devices from file. The RAM and the block devices
-# of the VM are not loaded by this command.
-#
-# @filename: the file to load the state of the devices from as binary
-# data. See xen-save-devices-state.txt for a description of the binary
-# format.
-#
-# Since: 2.7
-#
-# Example:
-#
-# -> { "execute": "xen-load-devices-state",
-#      "arguments": { "filename": "/tmp/resume" } }
-# <- { "return": {} }
-#
-##
-{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} }
-
-##
-# @GICCapability:
-#
-# The struct describes capability for a specific GIC (Generic
-# Interrupt Controller) version. These bits are not only decided by
-# QEMU/KVM software version, but also decided by the hardware that
-# the program is running upon.
-#
-# @version:  version of GIC to be described. Currently, only 2 and 3
-#            are supported.
-#
-# @emulated: whether current QEMU/hardware supports emulated GIC
-#            device in user space.
-#
-# @kernel:   whether current QEMU/hardware supports hardware
-#            accelerated GIC device in kernel.
-#
-# Since: 2.6
-##
-{ 'struct': 'GICCapability',
-  'data': { 'version': 'int',
-            'emulated': 'bool',
-            'kernel': 'bool' } }
-
-##
-# @query-gic-capabilities:
-#
-# This command is ARM-only. It will return a list of GICCapability
-# objects that describe its capability bits.
-#
-# Returns: a list of GICCapability objects.
-#
-# Since: 2.6
-#
-# Example:
-#
-# -> { "execute": "query-gic-capabilities" }
-# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
-#                 { "version": 3, "emulated": false, "kernel": true } ] }
-#
-##
-{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
-
-##
-# @CpuInstanceProperties:
-#
-# List of properties to be used for hotplugging a CPU instance,
-# it should be passed by management with device_add command when
-# a CPU is being hotplugged.
-#
-# @node-id: NUMA node ID the CPU belongs to
-# @socket-id: socket number within node/board the CPU belongs to
-# @core-id: core number within socket the CPU belongs to
-# @thread-id: thread number within core the CPU belongs to
-#
-# Note: currently there are 4 properties that could be present
-# but management should be prepared to pass through other
-# properties with device_add command to allow for future
-# interface extension. This also requires the filed names to be kept in
-# sync with the properties passed to -device/device_add.
-#
-# Since: 2.7
-##
-{ 'struct': 'CpuInstanceProperties',
-  'data': { '*node-id': 'int',
-            '*socket-id': 'int',
-            '*core-id': 'int',
-            '*thread-id': 'int'
-  }
-}
-
-##
-# @HotpluggableCPU:
-#
-# @type: CPU object type for usage with device_add command
-# @props: list of properties to be used for hotplugging CPU
-# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides
-# @qom-path: link to existing CPU object if CPU is present or
-#            omitted if CPU is not present.
-#
-# Since: 2.7
-##
-{ 'struct': 'HotpluggableCPU',
-  'data': { 'type': 'str',
-            'vcpus-count': 'int',
-            'props': 'CpuInstanceProperties',
-            '*qom-path': 'str'
-          }
-}
-
-##
-# @query-hotpluggable-cpus:
-#
-# Returns: a list of HotpluggableCPU objects.
-#
-# Since: 2.7
-#
-# Example:
-#
-# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8:
-#
-# -> { "execute": "query-hotpluggable-cpus" }
-# <- {"return": [
-#      { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core",
-#        "vcpus-count": 1 },
-#      { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core",
-#        "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"}
-#    ]}'
-#
-# For pc machine type started with -smp 1,maxcpus=2:
-#
-# -> { "execute": "query-hotpluggable-cpus" }
-# <- {"return": [
-#      {
-#         "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
-#         "props": {"core-id": 0, "socket-id": 1, "thread-id": 0}
-#      },
-#      {
-#         "qom-path": "/machine/unattached/device[0]",
-#         "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
-#         "props": {"core-id": 0, "socket-id": 0, "thread-id": 0}
-#      }
-#    ]}
-#
-# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu
-# (Since: 2.11):
-#
-# -> { "execute": "query-hotpluggable-cpus" }
-# <- {"return": [
-#      {
-#         "type": "qemu-s390x-cpu", "vcpus-count": 1,
-#         "props": { "core-id": 1 }
-#      },
-#      {
-#         "qom-path": "/machine/unattached/device[0]",
-#         "type": "qemu-s390x-cpu", "vcpus-count": 1,
-#         "props": { "core-id": 0 }
-#      }
-#    ]}
-#
-##
-{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'] }
-
-##
-# @GuidInfo:
-#
-# GUID information.
-#
-# @guid: the globally unique identifier
-#
-# Since: 2.9
-##
-{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} }
-
-##
-# @query-vm-generation-id:
-#
-# Show Virtual Machine Generation ID
-#
-# Since: 2.9
-##
-{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
-
-##
-# @watchdog-set-action:
-#
-# Set watchdog action
-#
-# Since: 2.11
-##
-{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+{ 'include': 'qapi/misc.json' }
diff --git a/qapi/misc.json b/qapi/misc.json
new file mode 100644
index 0000000000..225631bf7d
--- /dev/null
+++ b/qapi/misc.json
@@ -0,0 +1,3090 @@
+# -*- Mode: Python -*-
+#
+
+##
+# = Miscellanea
+##
+
+##
+# @qmp_capabilities:
+#
+# Enable QMP capabilities.
+#
+# Arguments: None.
+#
+# Example:
+#
+# -> { "execute": "qmp_capabilities" }
+# <- { "return": {} }
+#
+# Notes: This command is valid exactly when first connecting: it must be
+# issued before any other command will be accepted, and will fail once the
+# monitor is accepting other commands. (see qemu docs/interop/qmp-spec.txt)
+#
+# Since: 0.13
+#
+##
+{ 'command': 'qmp_capabilities' }
+
+##
+# @VersionTriple:
+#
+# A three-part version number.
+#
+# @major:  The major version number.
+#
+# @minor:  The minor version number.
+#
+# @micro:  The micro version number.
+#
+# Since: 2.4
+##
+{ 'struct': 'VersionTriple',
+  'data': {'major': 'int', 'minor': 'int', 'micro': 'int'} }
+
+
+##
+# @VersionInfo:
+#
+# A description of QEMU's version.
+#
+# @qemu:        The version of QEMU.  By current convention, a micro
+#               version of 50 signifies a development branch.  A micro version
+#               greater than or equal to 90 signifies a release candidate for
+#               the next minor version.  A micro version of less than 50
+#               signifies a stable release.
+#
+# @package:     QEMU will always set this field to an empty string.  Downstream
+#               versions of QEMU should set this to a non-empty string.  The
+#               exact format depends on the downstream however it highly
+#               recommended that a unique name is used.
+#
+# Since: 0.14.0
+##
+{ 'struct': 'VersionInfo',
+  'data': {'qemu': 'VersionTriple', 'package': 'str'} }
+
+##
+# @query-version:
+#
+# Returns the current version of QEMU.
+#
+# Returns:  A @VersionInfo object describing the current version of QEMU.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-version" }
+# <- {
+#       "return":{
+#          "qemu":{
+#             "major":0,
+#             "minor":11,
+#             "micro":5
+#          },
+#          "package":""
+#       }
+#    }
+#
+##
+{ 'command': 'query-version', 'returns': 'VersionInfo' }
+
+##
+# @CommandInfo:
+#
+# Information about a QMP command
+#
+# @name: The command name
+#
+# Since: 0.14.0
+##
+{ 'struct': 'CommandInfo', 'data': {'name': 'str'} }
+
+##
+# @query-commands:
+#
+# Return a list of supported QMP commands by this server
+#
+# Returns: A list of @CommandInfo for all supported commands
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-commands" }
+# <- {
+#      "return":[
+#         {
+#            "name":"query-balloon"
+#         },
+#         {
+#            "name":"system_powerdown"
+#         }
+#      ]
+#    }
+#
+# Note: This example has been shortened as the real response is too long.
+#
+##
+{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
+
+##
+# @LostTickPolicy:
+#
+# Policy for handling lost ticks in timer devices.
+#
+# @discard: throw away the missed tick(s) and continue with future injection
+#           normally.  Guest time may be delayed, unless the OS has explicit
+#           handling of lost ticks
+#
+# @delay: continue to deliver ticks at the normal rate.  Guest time will be
+#         delayed due to the late tick
+#
+# @merge: merge the missed tick(s) into one tick and inject.  Guest time
+#         may be delayed, depending on how the OS reacts to the merging
+#         of ticks
+#
+# @slew: deliver ticks at a higher rate to catch up with the missed tick. The
+#        guest time should not be delayed once catchup is complete.
+#
+# Since: 2.0
+##
+{ 'enum': 'LostTickPolicy',
+  'data': ['discard', 'delay', 'merge', 'slew' ] }
+
+##
+# @add_client:
+#
+# Allow client connections for VNC, Spice and socket based
+# character devices to be passed in to QEMU via SCM_RIGHTS.
+#
+# @protocol: protocol name. Valid names are "vnc", "spice" or the
+#            name of a character device (eg. from -chardev id=XXXX)
+#
+# @fdname: file descriptor name previously passed via 'getfd' command
+#
+# @skipauth: whether to skip authentication. Only applies
+#            to "vnc" and "spice" protocols
+#
+# @tls: whether to perform TLS. Only applies to the "spice"
+#       protocol
+#
+# Returns: nothing on success.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "add_client", "arguments": { "protocol": "vnc",
+#                                              "fdname": "myclient" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'add_client',
+  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',
+            '*tls': 'bool' } }
+
+##
+# @NameInfo:
+#
+# Guest name information.
+#
+# @name: The name of the guest
+#
+# Since: 0.14.0
+##
+{ 'struct': 'NameInfo', 'data': {'*name': 'str'} }
+
+##
+# @query-name:
+#
+# Return the name information of a guest.
+#
+# Returns: @NameInfo of the guest
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-name" }
+# <- { "return": { "name": "qemu-name" } }
+#
+##
+{ 'command': 'query-name', 'returns': 'NameInfo' }
+
+##
+# @KvmInfo:
+#
+# Information about support for KVM acceleration
+#
+# @enabled: true if KVM acceleration is active
+#
+# @present: true if KVM acceleration is built into this executable
+#
+# Since: 0.14.0
+##
+{ 'struct': 'KvmInfo', 'data': {'enabled': 'bool', 'present': 'bool'} }
+
+##
+# @query-kvm:
+#
+# Returns information about KVM acceleration
+#
+# Returns: @KvmInfo
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-kvm" }
+# <- { "return": { "enabled": true, "present": true } }
+#
+##
+{ 'command': 'query-kvm', 'returns': 'KvmInfo' }
+
+##
+# @UuidInfo:
+#
+# Guest UUID information (Universally Unique Identifier).
+#
+# @UUID: the UUID of the guest
+#
+# Since: 0.14.0
+#
+# Notes: If no UUID was specified for the guest, a null UUID is returned.
+##
+{ 'struct': 'UuidInfo', 'data': {'UUID': 'str'} }
+
+##
+# @query-uuid:
+#
+# Query the guest UUID information.
+#
+# Returns: The @UuidInfo for the guest
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-uuid" }
+# <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
+#
+##
+{ 'command': 'query-uuid', 'returns': 'UuidInfo' }
+
+##
+# @EventInfo:
+#
+# Information about a QMP event
+#
+# @name: The event name
+#
+# Since: 1.2.0
+##
+{ 'struct': 'EventInfo', 'data': {'name': 'str'} }
+
+##
+# @query-events:
+#
+# Return a list of supported QMP events by this server
+#
+# Returns: A list of @EventInfo for all supported events
+#
+# Since: 1.2.0
+#
+# Example:
+#
+# -> { "execute": "query-events" }
+# <- {
+#      "return": [
+#          {
+#             "name":"SHUTDOWN"
+#          },
+#          {
+#             "name":"RESET"
+#          }
+#       ]
+#    }
+#
+# Note: This example has been shortened as the real response is too long.
+#
+##
+{ 'command': 'query-events', 'returns': ['EventInfo'] }
+
+##
+# @CpuInfoArch:
+#
+# An enumeration of cpu types that enable additional information during
+# @query-cpus.
+#
+# Since: 2.6
+##
+{ 'enum': 'CpuInfoArch',
+  'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 'other' ] }
+
+##
+# @CpuInfo:
+#
+# Information about a virtual CPU
+#
+# @CPU: the index of the virtual CPU
+#
+# @current: this only exists for backwards compatibility and should be ignored
+#
+# @halted: true if the virtual CPU is in the halt state.  Halt usually refers
+#          to a processor specific low power mode.
+#
+# @qom_path: path to the CPU object in the QOM tree (since 2.4)
+#
+# @thread_id: ID of the underlying host thread
+#
+# @props: properties describing to which node/socket/core/thread
+#         virtual CPU belongs to, provided if supported by board (since 2.10)
+#
+# @arch: architecture of the cpu, which determines which additional fields
+#        will be listed (since 2.6)
+#
+# Since: 0.14.0
+#
+# Notes: @halted is a transient state that changes frequently.  By the time the
+#        data is sent to the client, the guest may no longer be halted.
+##
+{ 'union': 'CpuInfo',
+  'base': {'CPU': 'int', 'current': 'bool', 'halted': 'bool',
+           'qom_path': 'str', 'thread_id': 'int',
+           '*props': 'CpuInstanceProperties', 'arch': 'CpuInfoArch' },
+  'discriminator': 'arch',
+  'data': { 'x86': 'CpuInfoX86',
+            'sparc': 'CpuInfoSPARC',
+            'ppc': 'CpuInfoPPC',
+            'mips': 'CpuInfoMIPS',
+            'tricore': 'CpuInfoTricore',
+            'other': 'CpuInfoOther' } }
+
+##
+# @CpuInfoX86:
+#
+# Additional information about a virtual i386 or x86_64 CPU
+#
+# @pc: the 64-bit instruction pointer
+#
+# Since: 2.6
+##
+{ 'struct': 'CpuInfoX86', 'data': { 'pc': 'int' } }
+
+##
+# @CpuInfoSPARC:
+#
+# Additional information about a virtual SPARC CPU
+#
+# @pc: the PC component of the instruction pointer
+#
+# @npc: the NPC component of the instruction pointer
+#
+# Since: 2.6
+##
+{ 'struct': 'CpuInfoSPARC', 'data': { 'pc': 'int', 'npc': 'int' } }
+
+##
+# @CpuInfoPPC:
+#
+# Additional information about a virtual PPC CPU
+#
+# @nip: the instruction pointer
+#
+# Since: 2.6
+##
+{ 'struct': 'CpuInfoPPC', 'data': { 'nip': 'int' } }
+
+##
+# @CpuInfoMIPS:
+#
+# Additional information about a virtual MIPS CPU
+#
+# @PC: the instruction pointer
+#
+# Since: 2.6
+##
+{ 'struct': 'CpuInfoMIPS', 'data': { 'PC': 'int' } }
+
+##
+# @CpuInfoTricore:
+#
+# Additional information about a virtual Tricore CPU
+#
+# @PC: the instruction pointer
+#
+# Since: 2.6
+##
+{ 'struct': 'CpuInfoTricore', 'data': { 'PC': 'int' } }
+
+##
+# @CpuInfoOther:
+#
+# No additional information is available about the virtual CPU
+#
+# Since: 2.6
+#
+##
+{ 'struct': 'CpuInfoOther', 'data': { } }
+
+##
+# @query-cpus:
+#
+# Returns a list of information about each virtual CPU.
+#
+# Returns: a list of @CpuInfo for each virtual CPU
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-cpus" }
+# <- { "return": [
+#          {
+#             "CPU":0,
+#             "current":true,
+#             "halted":false,
+#             "qom_path":"/machine/unattached/device[0]",
+#             "arch":"x86",
+#             "pc":3227107138,
+#             "thread_id":3134
+#          },
+#          {
+#             "CPU":1,
+#             "current":false,
+#             "halted":true,
+#             "qom_path":"/machine/unattached/device[2]",
+#             "arch":"x86",
+#             "pc":7108165,
+#             "thread_id":3135
+#          }
+#       ]
+#    }
+#
+##
+{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }
+
+##
+# @IOThreadInfo:
+#
+# Information about an iothread
+#
+# @id: the identifier of the iothread
+#
+# @thread-id: ID of the underlying host thread
+#
+# @poll-max-ns: maximum polling time in ns, 0 means polling is disabled
+#               (since 2.9)
+#
+# @poll-grow: how many ns will be added to polling time, 0 means that it's not
+#             configured (since 2.9)
+#
+# @poll-shrink: how many ns will be removed from polling time, 0 means that
+#               it's not configured (since 2.9)
+#
+# Since: 2.0
+##
+{ 'struct': 'IOThreadInfo',
+  'data': {'id': 'str',
+           'thread-id': 'int',
+           'poll-max-ns': 'int',
+           'poll-grow': 'int',
+           'poll-shrink': 'int' } }
+
+##
+# @query-iothreads:
+#
+# Returns a list of information about each iothread.
+#
+# Note: this list excludes the QEMU main loop thread, which is not declared
+# using the -object iothread command-line option.  It is always the main thread
+# of the process.
+#
+# Returns: a list of @IOThreadInfo for each iothread
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-iothreads" }
+# <- { "return": [
+#          {
+#             "id":"iothread0",
+#             "thread-id":3134
+#          },
+#          {
+#             "id":"iothread1",
+#             "thread-id":3135
+#          }
+#       ]
+#    }
+#
+##
+{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'] }
+
+##
+# @BalloonInfo:
+#
+# Information about the guest balloon device.
+#
+# @actual: the number of bytes the balloon currently contains
+#
+# Since: 0.14.0
+#
+##
+{ 'struct': 'BalloonInfo', 'data': {'actual': 'int' } }
+
+##
+# @query-balloon:
+#
+# Return information about the balloon device.
+#
+# Returns: @BalloonInfo on success
+#
+#          If the balloon driver is enabled but not functional because the KVM
+#          kernel module cannot support it, KvmMissingCap
+#
+#          If no balloon device is present, DeviceNotActive
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-balloon" }
+# <- { "return": {
+#          "actual": 1073741824,
+#       }
+#    }
+#
+##
+{ 'command': 'query-balloon', 'returns': 'BalloonInfo' }
+
+##
+# @BALLOON_CHANGE:
+#
+# Emitted when the guest changes the actual BALLOON level. This value is
+# equivalent to the @actual field return by the 'query-balloon' command
+#
+# @actual: actual level of the guest memory balloon in bytes
+#
+# Note: this event is rate-limited.
+#
+# Since: 1.2
+#
+# Example:
+#
+# <- { "event": "BALLOON_CHANGE",
+#      "data": { "actual": 944766976 },
+#      "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'BALLOON_CHANGE',
+  'data': { 'actual': 'int' } }
+
+##
+# @PciMemoryRange:
+#
+# A PCI device memory region
+#
+# @base: the starting address (guest physical)
+#
+# @limit: the ending address (guest physical)
+#
+# Since: 0.14.0
+##
+{ 'struct': 'PciMemoryRange', 'data': {'base': 'int', 'limit': 'int'} }
+
+##
+# @PciMemoryRegion:
+#
+# Information about a PCI device I/O region.
+#
+# @bar: the index of the Base Address Register for this region
+#
+# @type: 'io' if the region is a PIO region
+#        'memory' if the region is a MMIO region
+#
+# @size: memory size
+#
+# @prefetch: if @type is 'memory', true if the memory is prefetchable
+#
+# @mem_type_64: if @type is 'memory', true if the BAR is 64-bit
+#
+# Since: 0.14.0
+##
+{ 'struct': 'PciMemoryRegion',
+  'data': {'bar': 'int', 'type': 'str', 'address': 'int', 'size': 'int',
+           '*prefetch': 'bool', '*mem_type_64': 'bool' } }
+
+##
+# @PciBusInfo:
+#
+# Information about a bus of a PCI Bridge device
+#
+# @number: primary bus interface number.  This should be the number of the
+#          bus the device resides on.
+#
+# @secondary: secondary bus interface number.  This is the number of the
+#             main bus for the bridge
+#
+# @subordinate: This is the highest number bus that resides below the
+#               bridge.
+#
+# @io_range: The PIO range for all devices on this bridge
+#
+# @memory_range: The MMIO range for all devices on this bridge
+#
+# @prefetchable_range: The range of prefetchable MMIO for all devices on
+#                      this bridge
+#
+# Since: 2.4
+##
+{ 'struct': 'PciBusInfo',
+  'data': {'number': 'int', 'secondary': 'int', 'subordinate': 'int',
+           'io_range': 'PciMemoryRange',
+           'memory_range': 'PciMemoryRange',
+           'prefetchable_range': 'PciMemoryRange' } }
+
+##
+# @PciBridgeInfo:
+#
+# Information about a PCI Bridge device
+#
+# @bus: information about the bus the device resides on
+#
+# @devices: a list of @PciDeviceInfo for each device on this bridge
+#
+# Since: 0.14.0
+##
+{ 'struct': 'PciBridgeInfo',
+  'data': {'bus': 'PciBusInfo', '*devices': ['PciDeviceInfo']} }
+
+##
+# @PciDeviceClass:
+#
+# Information about the Class of a PCI device
+#
+# @desc: a string description of the device's class
+#
+# @class: the class code of the device
+#
+# Since: 2.4
+##
+{ 'struct': 'PciDeviceClass',
+  'data': {'*desc': 'str', 'class': 'int'} }
+
+##
+# @PciDeviceId:
+#
+# Information about the Id of a PCI device
+#
+# @device: the PCI device id
+#
+# @vendor: the PCI vendor id
+#
+# Since: 2.4
+##
+{ 'struct': 'PciDeviceId',
+  'data': {'device': 'int', 'vendor': 'int'} }
+
+##
+# @PciDeviceInfo:
+#
+# Information about a PCI device
+#
+# @bus: the bus number of the device
+#
+# @slot: the slot the device is located in
+#
+# @function: the function of the slot used by the device
+#
+# @class_info: the class of the device
+#
+# @id: the PCI device id
+#
+# @irq: if an IRQ is assigned to the device, the IRQ number
+#
+# @qdev_id: the device name of the PCI device
+#
+# @pci_bridge: if the device is a PCI bridge, the bridge information
+#
+# @regions: a list of the PCI I/O regions associated with the device
+#
+# Notes: the contents of @class_info.desc are not stable and should only be
+#        treated as informational.
+#
+# Since: 0.14.0
+##
+{ 'struct': 'PciDeviceInfo',
+  'data': {'bus': 'int', 'slot': 'int', 'function': 'int',
+           'class_info': 'PciDeviceClass', 'id': 'PciDeviceId',
+           '*irq': 'int', 'qdev_id': 'str', '*pci_bridge': 'PciBridgeInfo',
+           'regions': ['PciMemoryRegion']} }
+
+##
+# @PciInfo:
+#
+# Information about a PCI bus
+#
+# @bus: the bus index
+#
+# @devices: a list of devices on this bus
+#
+# Since: 0.14.0
+##
+{ 'struct': 'PciInfo', 'data': {'bus': 'int', 'devices': ['PciDeviceInfo']} }
+
+##
+# @query-pci:
+#
+# Return information about the PCI bus topology of the guest.
+#
+# Returns: a list of @PciInfo for each PCI bus. Each bus is
+# represented by a json-object, which has a key with a json-array of
+# all PCI devices attached to it. Each device is represented by a
+# json-object.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "query-pci" }
+# <- { "return": [
+#          {
+#             "bus": 0,
+#             "devices": [
+#                {
+#                   "bus": 0,
+#                   "qdev_id": "",
+#                   "slot": 0,
+#                   "class_info": {
+#                      "class": 1536,
+#                      "desc": "Host bridge"
+#                   },
+#                   "id": {
+#                      "device": 32902,
+#                      "vendor": 4663
+#                   },
+#                   "function": 0,
+#                   "regions": [
+#                   ]
+#                },
+#                {
+#                   "bus": 0,
+#                   "qdev_id": "",
+#                   "slot": 1,
+#                   "class_info": {
+#                      "class": 1537,
+#                      "desc": "ISA bridge"
+#                   },
+#                   "id": {
+#                      "device": 32902,
+#                      "vendor": 28672
+#                   },
+#                   "function": 0,
+#                   "regions": [
+#                   ]
+#                },
+#                {
+#                   "bus": 0,
+#                   "qdev_id": "",
+#                   "slot": 1,
+#                   "class_info": {
+#                      "class": 257,
+#                      "desc": "IDE controller"
+#                   },
+#                   "id": {
+#                      "device": 32902,
+#                      "vendor": 28688
+#                   },
+#                   "function": 1,
+#                   "regions": [
+#                      {
+#                         "bar": 4,
+#                         "size": 16,
+#                         "address": 49152,
+#                         "type": "io"
+#                      }
+#                   ]
+#                },
+#                {
+#                   "bus": 0,
+#                   "qdev_id": "",
+#                   "slot": 2,
+#                   "class_info": {
+#                      "class": 768,
+#                      "desc": "VGA controller"
+#                   },
+#                   "id": {
+#                      "device": 4115,
+#                      "vendor": 184
+#                   },
+#                   "function": 0,
+#                   "regions": [
+#                      {
+#                         "prefetch": true,
+#                         "mem_type_64": false,
+#                         "bar": 0,
+#                         "size": 33554432,
+#                         "address": 4026531840,
+#                         "type": "memory"
+#                      },
+#                      {
+#                         "prefetch": false,
+#                         "mem_type_64": false,
+#                         "bar": 1,
+#                         "size": 4096,
+#                         "address": 4060086272,
+#                         "type": "memory"
+#                      },
+#                      {
+#                         "prefetch": false,
+#                         "mem_type_64": false,
+#                         "bar": 6,
+#                         "size": 65536,
+#                         "address": -1,
+#                         "type": "memory"
+#                      }
+#                   ]
+#                },
+#                {
+#                   "bus": 0,
+#                   "qdev_id": "",
+#                   "irq": 11,
+#                   "slot": 4,
+#                   "class_info": {
+#                      "class": 1280,
+#                      "desc": "RAM controller"
+#                   },
+#                   "id": {
+#                      "device": 6900,
+#                      "vendor": 4098
+#                   },
+#                   "function": 0,
+#                   "regions": [
+#                      {
+#                         "bar": 0,
+#                         "size": 32,
+#                         "address": 49280,
+#                         "type": "io"
+#                      }
+#                   ]
+#                }
+#             ]
+#          }
+#       ]
+#    }
+#
+# Note: This example has been shortened as the real response is too long.
+#
+##
+{ 'command': 'query-pci', 'returns': ['PciInfo'] }
+
+##
+# @quit:
+#
+# This command will cause the QEMU process to exit gracefully.  While every
+# attempt is made to send the QMP response before terminating, this is not
+# guaranteed.  When using this interface, a premature EOF would not be
+# unexpected.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "quit" }
+# <- { "return": {} }
+##
+{ 'command': 'quit' }
+
+##
+# @stop:
+#
+# Stop all guest VCPU execution.
+#
+# Since:  0.14.0
+#
+# Notes:  This function will succeed even if the guest is already in the stopped
+#         state.  In "inmigrate" state, it will ensure that the guest
+#         remains paused once migration finishes, as if the -S option was
+#         passed on the command line.
+#
+# Example:
+#
+# -> { "execute": "stop" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'stop' }
+
+##
+# @system_reset:
+#
+# Performs a hard reset of a guest.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "system_reset" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_reset' }
+
+##
+# @system_powerdown:
+#
+# Requests that a guest perform a powerdown operation.
+#
+# Since: 0.14.0
+#
+# Notes: A guest may or may not respond to this command.  This command
+#        returning does not indicate that a guest has accepted the request or
+#        that it has shut down.  Many guests will respond to this command by
+#        prompting the user in some way.
+# Example:
+#
+# -> { "execute": "system_powerdown" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_powerdown' }
+
+##
+# @cpu-add:
+#
+# Adds CPU with specified ID
+#
+# @id: ID of CPU to be created, valid values [0..max_cpus)
+#
+# Returns: Nothing on success
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "cpu-add", "arguments": { "id": 2 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'cpu-add', 'data': {'id': 'int'} }
+
+##
+# @memsave:
+#
+# Save a portion of guest memory to a file.
+#
+# @val: the virtual address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# @cpu-index: the index of the virtual CPU to use for translating the
+#                       virtual address (defaults to CPU 0)
+#
+# Returns: Nothing on success
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+#
+# Example:
+#
+# -> { "execute": "memsave",
+#      "arguments": { "val": 10,
+#                     "size": 100,
+#                     "filename": "/tmp/virtual-mem-dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'memsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
+
+##
+# @pmemsave:
+#
+# Save a portion of guest physical memory to a file.
+#
+# @val: the physical address of the guest to start from
+#
+# @size: the size of memory region to save
+#
+# @filename: the file to save the memory to as binary data
+#
+# Returns: Nothing on success
+#
+# Since: 0.14.0
+#
+# Notes: Errors were not reliably returned until 1.1
+#
+# Example:
+#
+# -> { "execute": "pmemsave",
+#      "arguments": { "val": 10,
+#                     "size": 100,
+#                     "filename": "/tmp/physical-mem-dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'pmemsave',
+  'data': {'val': 'int', 'size': 'int', 'filename': 'str'} }
+
+##
+# @cont:
+#
+# Resume guest VCPU execution.
+#
+# Since:  0.14.0
+#
+# Returns:  If successful, nothing
+#
+# Notes:  This command will succeed if the guest is currently running.  It
+#         will also succeed if the guest is in the "inmigrate" state; in
+#         this case, the effect of the command is to make sure the guest
+#         starts once migration finishes, removing the effect of the -S
+#         command line option if it was passed.
+#
+# Example:
+#
+# -> { "execute": "cont" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'cont' }
+
+##
+# @system_wakeup:
+#
+# Wakeup guest from suspend.  Does nothing in case the guest isn't suspended.
+#
+# Since:  1.1
+#
+# Returns:  nothing.
+#
+# Example:
+#
+# -> { "execute": "system_wakeup" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'system_wakeup' }
+
+##
+# @inject-nmi:
+#
+# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64).
+# The command fails when the guest doesn't support injecting.
+#
+# Returns:  If successful, nothing
+#
+# Since:  0.14.0
+#
+# Note: prior to 2.1, this command was only supported for x86 and s390 VMs
+#
+# Example:
+#
+# -> { "execute": "inject-nmi" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'inject-nmi' }
+
+##
+# @balloon:
+#
+# Request the balloon driver to change its balloon size.
+#
+# @value: the target size of the balloon in bytes
+#
+# Returns: Nothing on success
+#          If the balloon driver is enabled but not functional because the KVM
+#            kernel module cannot support it, KvmMissingCap
+#          If no balloon device is present, DeviceNotActive
+#
+# Notes: This command just issues a request to the guest.  When it returns,
+#        the balloon size may not have changed.  A guest can change the balloon
+#        size independent of this command.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "balloon", "arguments": { "value": 536870912 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'balloon', 'data': {'value': 'int'} }
+
+##
+# @human-monitor-command:
+#
+# Execute a command on the human monitor and return the output.
+#
+# @command-line: the command to execute in the human monitor
+#
+# @cpu-index: The CPU to use for commands that require an implicit CPU
+#
+# Returns: the output of the command as a string
+#
+# Since: 0.14.0
+#
+# Notes: This command only exists as a stop-gap.  Its use is highly
+#        discouraged.  The semantics of this command are not
+#        guaranteed: this means that command names, arguments and
+#        responses can change or be removed at ANY time.  Applications
+#        that rely on long term stability guarantees should NOT
+#        use this command.
+#
+#        Known limitations:
+#
+#        * This command is stateless, this means that commands that depend
+#          on state information (such as getfd) might not work
+#
+#        * Commands that prompt the user for data don't currently work
+#
+# Example:
+#
+# -> { "execute": "human-monitor-command",
+#      "arguments": { "command-line": "info kvm" } }
+# <- { "return": "kvm support: enabled\r\n" }
+#
+##
+{ 'command': 'human-monitor-command',
+  'data': {'command-line': 'str', '*cpu-index': 'int'},
+  'returns': 'str' }
+
+##
+# @ObjectPropertyInfo:
+#
+# @name: the name of the property
+#
+# @type: the type of the property.  This will typically come in one of four
+#        forms:
+#
+#        1) A primitive type such as 'u8', 'u16', 'bool', 'str', or 'double'.
+#           These types are mapped to the appropriate JSON type.
+#
+#        2) A child type in the form 'child<subtype>' where subtype is a qdev
+#           device type name.  Child properties create the composition tree.
+#
+#        3) A link type in the form 'link<subtype>' where subtype is a qdev
+#           device type name.  Link properties form the device model graph.
+#
+# Since: 1.2
+##
+{ 'struct': 'ObjectPropertyInfo',
+  'data': { 'name': 'str', 'type': 'str' } }
+
+##
+# @qom-list:
+#
+# This command will list any properties of a object given a path in the object
+# model.
+#
+# @path: the path within the object model.  See @qom-get for a description of
+#        this parameter.
+#
+# Returns: a list of @ObjectPropertyInfo that describe the properties of the
+#          object.
+#
+# Since: 1.2
+##
+{ 'command': 'qom-list',
+  'data': { 'path': 'str' },
+  'returns': [ 'ObjectPropertyInfo' ] }
+
+##
+# @qom-get:
+#
+# This command will get a property from a object model path and return the
+# value.
+#
+# @path: The path within the object model.  There are two forms of supported
+#        paths--absolute and partial paths.
+#
+#        Absolute paths are derived from the root object and can follow child<>
+#        or link<> properties.  Since they can follow link<> properties, they
+#        can be arbitrarily long.  Absolute paths look like absolute filenames
+#        and are prefixed  with a leading slash.
+#
+#        Partial paths look like relative filenames.  They do not begin
+#        with a prefix.  The matching rules for partial paths are subtle but
+#        designed to make specifying objects easy.  At each level of the
+#        composition tree, the partial path is matched as an absolute path.
+#        The first match is not returned.  At least two matches are searched
+#        for.  A successful result is only returned if only one match is
+#        found.  If more than one match is found, a flag is return to
+#        indicate that the match was ambiguous.
+#
+# @property: The property name to read
+#
+# Returns: The property value.  The type depends on the property
+#          type. child<> and link<> properties are returned as #str
+#          pathnames.  All integer property types (u8, u16, etc) are
+#          returned as #int.
+#
+# Since: 1.2
+##
+{ 'command': 'qom-get',
+  'data': { 'path': 'str', 'property': 'str' },
+  'returns': 'any' }
+
+##
+# @qom-set:
+#
+# This command will set a property from a object model path.
+#
+# @path: see @qom-get for a description of this parameter
+#
+# @property: the property name to set
+#
+# @value: a value who's type is appropriate for the property type.  See @qom-get
+#         for a description of type mapping.
+#
+# Since: 1.2
+##
+{ 'command': 'qom-set',
+  'data': { 'path': 'str', 'property': 'str', 'value': 'any' } }
+
+##
+# @change:
+#
+# This command is multiple commands multiplexed together.
+#
+# @device: This is normally the name of a block device but it may also be 'vnc'.
+#          when it's 'vnc', then sub command depends on @target
+#
+# @target: If @device is a block device, then this is the new filename.
+#          If @device is 'vnc', then if the value 'password' selects the vnc
+#          change password command.   Otherwise, this specifies a new server URI
+#          address to listen to for VNC connections.
+#
+# @arg:    If @device is a block device, then this is an optional format to open
+#          the device with.
+#          If @device is 'vnc' and @target is 'password', this is the new VNC
+#          password to set.  See change-vnc-password for additional notes.
+#
+# Returns: Nothing on success.
+#          If @device is not a valid block device, DeviceNotFound
+#
+# Notes:  This interface is deprecated, and it is strongly recommended that you
+#         avoid using it.  For changing block devices, use
+#         blockdev-change-medium; for changing VNC parameters, use
+#         change-vnc-password.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# 1. Change a removable medium
+#
+# -> { "execute": "change",
+#      "arguments": { "device": "ide1-cd0",
+#                     "target": "/srv/images/Fedora-12-x86_64-DVD.iso" } }
+# <- { "return": {} }
+#
+# 2. Change VNC password
+#
+# -> { "execute": "change",
+#      "arguments": { "device": "vnc", "target": "password",
+#                     "arg": "foobar1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'change',
+  'data': {'device': 'str', 'target': 'str', '*arg': 'str'} }
+
+##
+# @ObjectTypeInfo:
+#
+# This structure describes a search result from @qom-list-types
+#
+# @name: the type name found in the search
+#
+# @abstract: the type is abstract and can't be directly instantiated.
+#            Omitted if false. (since 2.10)
+#
+# @parent: Name of parent type, if any (since 2.10)
+#
+# Since: 1.1
+##
+{ 'struct': 'ObjectTypeInfo',
+  'data': { 'name': 'str', '*abstract': 'bool', '*parent': 'str' } }
+
+##
+# @qom-list-types:
+#
+# This command will return a list of types given search parameters
+#
+# @implements: if specified, only return types that implement this type name
+#
+# @abstract: if true, include abstract types in the results
+#
+# Returns: a list of @ObjectTypeInfo or an empty list if no results are found
+#
+# Since: 1.1
+##
+{ 'command': 'qom-list-types',
+  'data': { '*implements': 'str', '*abstract': 'bool' },
+  'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @DevicePropertyInfo:
+#
+# Information about device properties.
+#
+# @name: the name of the property
+# @type: the typename of the property
+# @description: if specified, the description of the property.
+#               (since 2.2)
+#
+# Since: 1.2
+##
+{ 'struct': 'DevicePropertyInfo',
+  'data': { 'name': 'str', 'type': 'str', '*description': 'str' } }
+
+##
+# @device-list-properties:
+#
+# List properties associated with a device.
+#
+# @typename: the type name of a device
+#
+# Returns: a list of DevicePropertyInfo describing a devices properties
+#
+# Since: 1.2
+##
+{ 'command': 'device-list-properties',
+  'data': { 'typename': 'str'},
+  'returns': [ 'DevicePropertyInfo' ] }
+
+##
+# @xen-set-global-dirty-log:
+#
+# Enable or disable the global dirty log mode.
+#
+# @enable: true to enable, false to disable.
+#
+# Returns: nothing
+#
+# Since: 1.3
+#
+# Example:
+#
+# -> { "execute": "xen-set-global-dirty-log",
+#      "arguments": { "enable": true } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'xen-set-global-dirty-log', 'data': { 'enable': 'bool' } }
+
+##
+# @device_add:
+#
+# @driver: the name of the new device's driver
+#
+# @bus: the device's parent bus (device tree path)
+#
+# @id: the device's ID, must be unique
+#
+# Additional arguments depend on the type.
+#
+# Add a device.
+#
+# Notes:
+# 1. For detailed information about this command, please refer to the
+#    'docs/qdev-device-use.txt' file.
+#
+# 2. It's possible to list device properties by running QEMU with the
+#    "-device DEVICE,help" command-line argument, where DEVICE is the
+#    device's name
+#
+# Example:
+#
+# -> { "execute": "device_add",
+#      "arguments": { "driver": "e1000", "id": "net1",
+#                     "bus": "pci.0",
+#                     "mac": "52:54:00:12:34:56" } }
+# <- { "return": {} }
+#
+# TODO: This command effectively bypasses QAPI completely due to its
+# "additional arguments" business.  It shouldn't have been added to
+# the schema in this form.  It should be qapified properly, or
+# replaced by a properly qapified command.
+#
+# Since: 0.13
+##
+{ 'command': 'device_add',
+  'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
+  'gen': false } # so we can get the additional arguments
+
+##
+# @device_del:
+#
+# Remove a device from a guest
+#
+# @id: the device's ID or QOM path
+#
+# Returns: Nothing on success
+#          If @id is not a valid device, DeviceNotFound
+#
+# Notes: When this command completes, the device may not be removed from the
+#        guest.  Hot removal is an operation that requires guest cooperation.
+#        This command merely requests that the guest begin the hot removal
+#        process.  Completion of the device removal process is signaled with a
+#        DEVICE_DELETED event. Guest reset will automatically complete removal
+#        for all devices.
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "device_del",
+#      "arguments": { "id": "net1" } }
+# <- { "return": {} }
+#
+# -> { "execute": "device_del",
+#      "arguments": { "id": "/machine/peripheral-anon/device[0]" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'device_del', 'data': {'id': 'str'} }
+
+##
+# @DEVICE_DELETED:
+#
+# Emitted whenever the device removal completion is acknowledged by the guest.
+# At this point, it's safe to reuse the specified device ID. Device removal can
+# be initiated by the guest or by HMP/QMP commands.
+#
+# @device: device name
+#
+# @path: device path
+#
+# Since: 1.5
+#
+# Example:
+#
+# <- { "event": "DEVICE_DELETED",
+#      "data": { "device": "virtio-net-pci-0",
+#                "path": "/machine/peripheral/virtio-net-pci-0" },
+#      "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'DEVICE_DELETED',
+  'data': { '*device': 'str', 'path': 'str' } }
+
+##
+# @DumpGuestMemoryFormat:
+#
+# An enumeration of guest-memory-dump's format.
+#
+# @elf: elf format
+#
+# @kdump-zlib: kdump-compressed format with zlib-compressed
+#
+# @kdump-lzo: kdump-compressed format with lzo-compressed
+#
+# @kdump-snappy: kdump-compressed format with snappy-compressed
+#
+# Since: 2.0
+##
+{ 'enum': 'DumpGuestMemoryFormat',
+  'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
+
+##
+# @dump-guest-memory:
+#
+# Dump guest's memory to vmcore. It is a synchronous operation that can take
+# very long depending on the amount of guest memory.
+#
+# @paging: if true, do paging to get guest's memory mapping. This allows
+#          using gdb to process the core file.
+#
+#          IMPORTANT: this option can make QEMU allocate several gigabytes
+#                     of RAM. This can happen for a large guest, or a
+#                     malicious guest pretending to be large.
+#
+#          Also, paging=true has the following limitations:
+#
+#             1. The guest may be in a catastrophic state or can have corrupted
+#                memory, which cannot be trusted
+#             2. The guest can be in real-mode even if paging is enabled. For
+#                example, the guest uses ACPI to sleep, and ACPI sleep state
+#                goes in real-mode
+#             3. Currently only supported on i386 and x86_64.
+#
+# @protocol: the filename or file descriptor of the vmcore. The supported
+#            protocols are:
+#
+#            1. file: the protocol starts with "file:", and the following
+#               string is the file's path.
+#            2. fd: the protocol starts with "fd:", and the following string
+#               is the fd's name.
+#
+# @detach: if true, QMP will return immediately rather than
+#          waiting for the dump to finish. The user can track progress
+#          using "query-dump". (since 2.6).
+#
+# @begin: if specified, the starting physical address.
+#
+# @length: if specified, the memory size, in bytes. If you don't
+#          want to dump all guest's memory, please specify the start @begin
+#          and @length
+#
+# @format: if specified, the format of guest memory dump. But non-elf
+#          format is conflict with paging and filter, ie. @paging, @begin and
+#          @length is not allowed to be specified with non-elf @format at the
+#          same time (since 2.0)
+#
+# Note: All boolean arguments default to false
+#
+# Returns: nothing on success
+#
+# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "dump-guest-memory",
+#      "arguments": { "protocol": "fd:dump" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-guest-memory',
+  'data': { 'paging': 'bool', 'protocol': 'str', '*detach': 'bool',
+            '*begin': 'int', '*length': 'int',
+            '*format': 'DumpGuestMemoryFormat'} }
+
+##
+# @DumpStatus:
+#
+# Describe the status of a long-running background guest memory dump.
+#
+# @none: no dump-guest-memory has started yet.
+#
+# @active: there is one dump running in background.
+#
+# @completed: the last dump has finished successfully.
+#
+# @failed: the last dump has failed.
+#
+# Since: 2.6
+##
+{ 'enum': 'DumpStatus',
+  'data': [ 'none', 'active', 'completed', 'failed' ] }
+
+##
+# @DumpQueryResult:
+#
+# The result format for 'query-dump'.
+#
+# @status: enum of @DumpStatus, which shows current dump status
+#
+# @completed: bytes written in latest dump (uncompressed)
+#
+# @total: total bytes to be written in latest dump (uncompressed)
+#
+# Since: 2.6
+##
+{ 'struct': 'DumpQueryResult',
+  'data': { 'status': 'DumpStatus',
+            'completed': 'int',
+            'total': 'int' } }
+
+##
+# @query-dump:
+#
+# Query latest dump status.
+#
+# Returns: A @DumpStatus object showing the dump status.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-dump" }
+# <- { "return": { "status": "active", "completed": 1024000,
+#                  "total": 2048000 } }
+#
+##
+{ 'command': 'query-dump', 'returns': 'DumpQueryResult' }
+
+##
+# @DUMP_COMPLETED:
+#
+# Emitted when background dump has completed
+#
+# @result: DumpQueryResult type described in qapi-schema.json.
+#
+# @error: human-readable error string that provides
+#         hint on why dump failed. Only presents on failure. The
+#         user should not try to interpret the error string.
+#
+# Since: 2.6
+#
+# Example:
+#
+# { "event": "DUMP_COMPLETED",
+#   "data": {"result": {"total": 1090650112, "status": "completed",
+#                       "completed": 1090650112} } }
+#
+##
+{ 'event': 'DUMP_COMPLETED' ,
+  'data': { 'result': 'DumpQueryResult', '*error': 'str' } }
+
+##
+# @DumpGuestMemoryCapability:
+#
+# A list of the available formats for dump-guest-memory
+#
+# Since: 2.0
+##
+{ 'struct': 'DumpGuestMemoryCapability',
+  'data': {
+      'formats': ['DumpGuestMemoryFormat'] } }
+
+##
+# @query-dump-guest-memory-capability:
+#
+# Returns the available formats for dump-guest-memory
+#
+# Returns:  A @DumpGuestMemoryCapability object listing available formats for
+#           dump-guest-memory
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "query-dump-guest-memory-capability" }
+# <- { "return": { "formats":
+#                  ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] }
+#
+##
+{ 'command': 'query-dump-guest-memory-capability',
+  'returns': 'DumpGuestMemoryCapability' }
+
+##
+# @dump-skeys:
+#
+# Dump guest's storage keys
+#
+# @filename: the path to the file to dump to
+#
+# This command is only supported on s390 architecture.
+#
+# Since: 2.5
+#
+# Example:
+#
+# -> { "execute": "dump-skeys",
+#      "arguments": { "filename": "/tmp/skeys" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'dump-skeys',
+  'data': { 'filename': 'str' } }
+
+##
+# @object-add:
+#
+# Create a QOM object.
+#
+# @qom-type: the class name for the object to be created
+#
+# @id: the name of the new object
+#
+# @props: a dictionary of properties to be passed to the backend
+#
+# Returns: Nothing on success
+#          Error if @qom-type is not a valid class name
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "object-add",
+#      "arguments": { "qom-type": "rng-random", "id": "rng1",
+#                     "props": { "filename": "/dev/hwrng" } } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'object-add',
+  'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} }
+
+##
+# @object-del:
+#
+# Remove a QOM object.
+#
+# @id: the name of the QOM object to remove
+#
+# Returns: Nothing on success
+#          Error if @id is not a valid id for a QOM object
+#
+# Since: 2.0
+#
+# Example:
+#
+# -> { "execute": "object-del", "arguments": { "id": "rng1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'object-del', 'data': {'id': 'str'} }
+
+##
+# @getfd:
+#
+# Receive a file descriptor via SCM rights and assign it a name
+#
+# @fdname: file descriptor name
+#
+# Returns: Nothing on success
+#
+# Since: 0.14.0
+#
+# Notes: If @fdname already exists, the file descriptor assigned to
+#        it will be closed and replaced by the received file
+#        descriptor.
+#
+#        The 'closefd' command can be used to explicitly close the
+#        file descriptor when it is no longer needed.
+#
+# Example:
+#
+# -> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'getfd', 'data': {'fdname': 'str'} }
+
+##
+# @closefd:
+#
+# Close a file descriptor previously passed via SCM rights
+#
+# @fdname: file descriptor name
+#
+# Returns: Nothing on success
+#
+# Since: 0.14.0
+#
+# Example:
+#
+# -> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'closefd', 'data': {'fdname': 'str'} }
+
+##
+# @MachineInfo:
+#
+# Information describing a machine.
+#
+# @name: the name of the machine
+#
+# @alias: an alias for the machine name
+#
+# @is-default: whether the machine is default
+#
+# @cpu-max: maximum number of CPUs supported by the machine type
+#           (since 1.5.0)
+#
+# @hotpluggable-cpus: cpu hotplug via -device is supported (since 2.7.0)
+#
+# Since: 1.2.0
+##
+{ 'struct': 'MachineInfo',
+  'data': { 'name': 'str', '*alias': 'str',
+            '*is-default': 'bool', 'cpu-max': 'int',
+            'hotpluggable-cpus': 'bool'} }
+
+##
+# @query-machines:
+#
+# Return a list of supported machines
+#
+# Returns: a list of MachineInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
+
+##
+# @CpuDefinitionInfo:
+#
+# Virtual CPU definition.
+#
+# @name: the name of the CPU definition
+#
+# @migration-safe: whether a CPU definition can be safely used for
+#                  migration in combination with a QEMU compatibility machine
+#                  when migrating between different QMU versions and between
+#                  hosts with different sets of (hardware or software)
+#                  capabilities. If not provided, information is not available
+#                  and callers should not assume the CPU definition to be
+#                  migration-safe. (since 2.8)
+#
+# @static: whether a CPU definition is static and will not change depending on
+#          QEMU version, machine type, machine options and accelerator options.
+#          A static model is always migration-safe. (since 2.8)
+#
+# @unavailable-features: List of properties that prevent
+#                        the CPU model from running in the current
+#                        host. (since 2.8)
+# @typename: Type name that can be used as argument to @device-list-properties,
+#            to introspect properties configurable using -cpu or -global.
+#            (since 2.9)
+#
+# @unavailable-features is a list of QOM property names that
+# represent CPU model attributes that prevent the CPU from running.
+# If the QOM property is read-only, that means there's no known
+# way to make the CPU model run in the current host. Implementations
+# that choose not to provide specific information return the
+# property name "type".
+# If the property is read-write, it means that it MAY be possible
+# to run the CPU model in the current host if that property is
+# changed. Management software can use it as hints to suggest or
+# choose an alternative for the user, or just to generate meaningful
+# error messages explaining why the CPU model can't be used.
+# If @unavailable-features is an empty list, the CPU model is
+# runnable using the current host and machine-type.
+# If @unavailable-features is not present, runnability
+# information for the CPU is not available.
+#
+# Since: 1.2.0
+##
+{ 'struct': 'CpuDefinitionInfo',
+  'data': { 'name': 'str', '*migration-safe': 'bool', 'static': 'bool',
+            '*unavailable-features': [ 'str' ], 'typename': 'str' } }
+
+##
+# @MemoryInfo:
+#
+# Actual memory information in bytes.
+#
+# @base-memory: size of "base" memory specified with command line
+#               option -m.
+#
+# @plugged-memory: size of memory that can be hot-unplugged. This field
+#                  is omitted if target doesn't support memory hotplug
+#                  (i.e. CONFIG_MEM_HOTPLUG not defined on build time).
+#
+# Since: 2.11.0
+##
+{ 'struct': 'MemoryInfo',
+  'data'  : { 'base-memory': 'size', '*plugged-memory': 'size' } }
+
+##
+# @query-memory-size-summary:
+#
+# Return the amount of initially allocated and present hotpluggable (if
+# enabled) memory in bytes.
+#
+# Example:
+#
+# -> { "execute": "query-memory-size-summary" }
+# <- { "return": { "base-memory": 4294967296, "plugged-memory": 0 } }
+#
+# Since: 2.11.0
+##
+{ 'command': 'query-memory-size-summary', 'returns': 'MemoryInfo' }
+
+##
+# @query-cpu-definitions:
+#
+# Return a list of supported virtual CPU definitions
+#
+# Returns: a list of CpuDefInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] }
+
+##
+# @CpuModelInfo:
+#
+# Virtual CPU model.
+#
+# A CPU model consists of the name of a CPU definition, to which
+# delta changes are applied (e.g. features added/removed). Most magic values
+# that an architecture might require should be hidden behind the name.
+# However, if required, architectures can expose relevant properties.
+#
+# @name: the name of the CPU definition the model is based on
+# @props: a dictionary of QOM properties to be applied
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelInfo',
+  'data': { 'name': 'str',
+            '*props': 'any' } }
+
+##
+# @CpuModelExpansionType:
+#
+# An enumeration of CPU model expansion types.
+#
+# @static: Expand to a static CPU model, a combination of a static base
+#          model name and property delta changes. As the static base model will
+#          never change, the expanded CPU model will be the same, independant of
+#          independent of QEMU version, machine type, machine options, and
+#          accelerator options. Therefore, the resulting model can be used by
+#          tooling without having to specify a compatibility machine - e.g. when
+#          displaying the "host" model. static CPU models are migration-safe.
+#
+# @full: Expand all properties. The produced model is not guaranteed to be
+#        migration-safe, but allows tooling to get an insight and work with
+#        model details.
+#
+# Note: When a non-migration-safe CPU model is expanded in static mode, some
+# features enabled by the CPU model may be omitted, because they can't be
+# implemented by a static CPU model definition (e.g. cache info passthrough and
+# PMU passthrough in x86). If you need an accurate representation of the
+# features enabled by a non-migration-safe CPU model, use @full. If you need a
+# static representation that will keep ABI compatibility even when changing QEMU
+# version or machine-type, use @static (but keep in mind that some features may
+# be omitted).
+#
+# Since: 2.8.0
+##
+{ 'enum': 'CpuModelExpansionType',
+  'data': [ 'static', 'full' ] }
+
+
+##
+# @CpuModelExpansionInfo:
+#
+# The result of a cpu model expansion.
+#
+# @model: the expanded CpuModelInfo.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelExpansionInfo',
+  'data': { 'model': 'CpuModelInfo' } }
+
+
+##
+# @query-cpu-model-expansion:
+#
+# Expands a given CPU model (or a combination of CPU model + additional options)
+# to different granularities, allowing tooling to get an understanding what a
+# specific CPU model looks like in QEMU under a certain configuration.
+#
+# This interface can be used to query the "host" CPU model.
+#
+# The data returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model  may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support all expansion types. s390x supports
+# "full" and "static".
+#
+# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
+#          not supported, if the model cannot be expanded, if the model contains
+#          an unknown CPU definition name, unknown properties or properties
+#          with a wrong type. Also returns an error if an expansion type is
+#          not supported.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-expansion',
+  'data': { 'type': 'CpuModelExpansionType',
+            'model': 'CpuModelInfo' },
+  'returns': 'CpuModelExpansionInfo' }
+
+##
+# @CpuModelCompareResult:
+#
+# An enumeration of CPU model comparation results. The result is usually
+# calculated using e.g. CPU features or CPU generations.
+#
+# @incompatible: If model A is incompatible to model B, model A is not
+#                guaranteed to run where model B runs and the other way around.
+#
+# @identical: If model A is identical to model B, model A is guaranteed to run
+#             where model B runs and the other way around.
+#
+# @superset: If model A is a superset of model B, model B is guaranteed to run
+#            where model A runs. There are no guarantees about the other way.
+#
+# @subset: If model A is a subset of model B, model A is guaranteed to run
+#          where model B runs. There are no guarantees about the other way.
+#
+# Since: 2.8.0
+##
+{ 'enum': 'CpuModelCompareResult',
+  'data': [ 'incompatible', 'identical', 'superset', 'subset' ] }
+
+##
+# @CpuModelCompareInfo:
+#
+# The result of a CPU model comparison.
+#
+# @result: The result of the compare operation.
+# @responsible-properties: List of properties that led to the comparison result
+#                          not being identical.
+#
+# @responsible-properties is a list of QOM property names that led to
+# both CPUs not being detected as identical. For identical models, this
+# list is empty.
+# If a QOM property is read-only, that means there's no known way to make the
+# CPU models identical. If the special property name "type" is included, the
+# models are by definition not identical and cannot be made identical.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelCompareInfo',
+  'data': {'result': 'CpuModelCompareResult',
+           'responsible-properties': ['str']
+          }
+}
+
+##
+# @query-cpu-model-comparison:
+#
+# Compares two CPU models, returning how they compare in a specific
+# configuration. The results indicates how both models compare regarding
+# runnability. This result can be used by tooling to make decisions if a
+# certain CPU model will run in a certain configuration or if a compatible
+# CPU model has to be created by baselining.
+#
+# Usually, a CPU model is compared against the maximum possible CPU model
+# of a certain configuration (e.g. the "host" model for KVM). If that CPU
+# model is identical or a subset, it will run in that configuration.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support comparing CPU models. s390x supports
+# comparing CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if comparing CPU models is
+#          not supported, if a model cannot be used, if a model contains
+#          an unknown cpu definition name, unknown properties or properties
+#          with wrong types.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-comparison',
+  'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
+  'returns': 'CpuModelCompareInfo' }
+
+##
+# @CpuModelBaselineInfo:
+#
+# The result of a CPU model baseline.
+#
+# @model: the baselined CpuModelInfo.
+#
+# Since: 2.8.0
+##
+{ 'struct': 'CpuModelBaselineInfo',
+  'data': { 'model': 'CpuModelInfo' } }
+
+##
+# @query-cpu-model-baseline:
+#
+# Baseline two CPU models, creating a compatible third model. The created
+# model will always be a static, migration-safe CPU model (see "static"
+# CPU model expansion for details).
+#
+# This interface can be used by tooling to create a compatible CPU model out
+# two CPU models. The created CPU model will be identical to or a subset of
+# both CPU models when comparing them. Therefore, the created CPU model is
+# guaranteed to run where the given CPU models run.
+#
+# The result returned by this command may be affected by:
+#
+# * QEMU version: CPU models may look different depending on the QEMU version.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine-type: CPU model may look different depending on the machine-type.
+#   (Except for CPU models reported as "static" in query-cpu-definitions.)
+# * machine options (including accelerator): in some architectures, CPU models
+#   may look different depending on machine and accelerator options. (Except for
+#   CPU models reported as "static" in query-cpu-definitions.)
+# * "-cpu" arguments and global properties: arguments to the -cpu option and
+#   global properties may affect expansion of CPU models. Using
+#   query-cpu-model-expansion while using these is not advised.
+#
+# Some architectures may not support baselining CPU models. s390x supports
+# baselining CPU models.
+#
+# Returns: a CpuModelBaselineInfo. Returns an error if baselining CPU models is
+#          not supported, if a model cannot be used, if a model contains
+#          an unknown cpu definition name, unknown properties or properties
+#          with wrong types.
+#
+# Since: 2.8.0
+##
+{ 'command': 'query-cpu-model-baseline',
+  'data': { 'modela': 'CpuModelInfo',
+            'modelb': 'CpuModelInfo' },
+  'returns': 'CpuModelBaselineInfo' }
+
+##
+# @AddfdInfo:
+#
+# Information about a file descriptor that was added to an fd set.
+#
+# @fdset-id: The ID of the fd set that @fd was added to.
+#
+# @fd: The file descriptor that was received via SCM rights and
+#      added to the fd set.
+#
+# Since: 1.2.0
+##
+{ 'struct': 'AddfdInfo', 'data': {'fdset-id': 'int', 'fd': 'int'} }
+
+##
+# @add-fd:
+#
+# Add a file descriptor, that was passed via SCM rights, to an fd set.
+#
+# @fdset-id: The ID of the fd set to add the file descriptor to.
+#
+# @opaque: A free-form string that can be used to describe the fd.
+#
+# Returns: @AddfdInfo on success
+#
+#          If file descriptor was not received, FdNotSupplied
+#
+#          If @fdset-id is a negative value, InvalidParameterValue
+#
+# Notes: The list of fd sets is shared by all monitor connections.
+#
+#        If @fdset-id is not specified, a new fd set will be created.
+#
+# Since: 1.2.0
+#
+# Example:
+#
+# -> { "execute": "add-fd", "arguments": { "fdset-id": 1 } }
+# <- { "return": { "fdset-id": 1, "fd": 3 } }
+#
+##
+{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
+  'returns': 'AddfdInfo' }
+
+##
+# @remove-fd:
+#
+# Remove a file descriptor from an fd set.
+#
+# @fdset-id: The ID of the fd set that the file descriptor belongs to.
+#
+# @fd: The file descriptor that is to be removed.
+#
+# Returns: Nothing on success
+#          If @fdset-id or @fd is not found, FdNotFound
+#
+# Since: 1.2.0
+#
+# Notes: The list of fd sets is shared by all monitor connections.
+#
+#        If @fd is not specified, all file descriptors in @fdset-id
+#        will be removed.
+#
+# Example:
+#
+# -> { "execute": "remove-fd", "arguments": { "fdset-id": 1, "fd": 3 } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'remove-fd', 'data': {'fdset-id': 'int', '*fd': 'int'} }
+
+##
+# @FdsetFdInfo:
+#
+# Information about a file descriptor that belongs to an fd set.
+#
+# @fd: The file descriptor value.
+#
+# @opaque: A free-form string that can be used to describe the fd.
+#
+# Since: 1.2.0
+##
+{ 'struct': 'FdsetFdInfo',
+  'data': {'fd': 'int', '*opaque': 'str'} }
+
+##
+# @FdsetInfo:
+#
+# Information about an fd set.
+#
+# @fdset-id: The ID of the fd set.
+#
+# @fds: A list of file descriptors that belong to this fd set.
+#
+# Since: 1.2.0
+##
+{ 'struct': 'FdsetInfo',
+  'data': {'fdset-id': 'int', 'fds': ['FdsetFdInfo']} }
+
+##
+# @query-fdsets:
+#
+# Return information describing all fd sets.
+#
+# Returns: A list of @FdsetInfo
+#
+# Since: 1.2.0
+#
+# Note: The list of fd sets is shared by all monitor connections.
+#
+# Example:
+#
+# -> { "execute": "query-fdsets" }
+# <- { "return": [
+#        {
+#          "fds": [
+#            {
+#              "fd": 30,
+#              "opaque": "rdonly:/path/to/file"
+#            },
+#            {
+#              "fd": 24,
+#              "opaque": "rdwr:/path/to/file"
+#            }
+#          ],
+#          "fdset-id": 1
+#        },
+#        {
+#          "fds": [
+#            {
+#              "fd": 28
+#            },
+#            {
+#              "fd": 29
+#            }
+#          ],
+#          "fdset-id": 0
+#        }
+#      ]
+#    }
+#
+##
+{ 'command': 'query-fdsets', 'returns': ['FdsetInfo'] }
+
+##
+# @TargetInfo:
+#
+# Information describing the QEMU target.
+#
+# @arch: the target architecture (eg "x86_64", "i386", etc)
+#
+# Since: 1.2.0
+##
+{ 'struct': 'TargetInfo',
+  'data': { 'arch': 'str' } }
+
+##
+# @query-target:
+#
+# Return information about the target for this QEMU
+#
+# Returns: TargetInfo
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-target', 'returns': 'TargetInfo' }
+
+##
+# @AcpiTableOptions:
+#
+# Specify an ACPI table on the command line to load.
+#
+# At most one of @file and @data can be specified. The list of files specified
+# by any one of them is loaded and concatenated in order. If both are omitted,
+# @data is implied.
+#
+# Other fields / optargs can be used to override fields of the generic ACPI
+# table header; refer to the ACPI specification 5.0, section 5.2.6 System
+# Description Table Header. If a header field is not overridden, then the
+# corresponding value from the concatenated blob is used (in case of @file), or
+# it is filled in with a hard-coded value (in case of @data).
+#
+# String fields are copied into the matching ACPI member from lowest address
+# upwards, and silently truncated / NUL-padded to length.
+#
+# @sig: table signature / identifier (4 bytes)
+#
+# @rev: table revision number (dependent on signature, 1 byte)
+#
+# @oem_id: OEM identifier (6 bytes)
+#
+# @oem_table_id: OEM table identifier (8 bytes)
+#
+# @oem_rev: OEM-supplied revision number (4 bytes)
+#
+# @asl_compiler_id: identifier of the utility that created the table
+#                   (4 bytes)
+#
+# @asl_compiler_rev: revision number of the utility that created the
+#                    table (4 bytes)
+#
+# @file: colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob is expected to
+#        have an ACPI table header. At least one file is required. This field
+#        excludes @data.
+#
+# @data: colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob must not have an
+#        ACPI table header. At least one file is required. This field excludes
+#        @file.
+#
+# Since: 1.5
+##
+{ 'struct': 'AcpiTableOptions',
+  'data': {
+    '*sig':               'str',
+    '*rev':               'uint8',
+    '*oem_id':            'str',
+    '*oem_table_id':      'str',
+    '*oem_rev':           'uint32',
+    '*asl_compiler_id':   'str',
+    '*asl_compiler_rev':  'uint32',
+    '*file':              'str',
+    '*data':              'str' }}
+
+##
+# @CommandLineParameterType:
+#
+# Possible types for an option parameter.
+#
+# @string: accepts a character string
+#
+# @boolean: accepts "on" or "off"
+#
+# @number: accepts a number
+#
+# @size: accepts a number followed by an optional suffix (K)ilo,
+#        (M)ega, (G)iga, (T)era
+#
+# Since: 1.5
+##
+{ 'enum': 'CommandLineParameterType',
+  'data': ['string', 'boolean', 'number', 'size'] }
+
+##
+# @CommandLineParameterInfo:
+#
+# Details about a single parameter of a command line option.
+#
+# @name: parameter name
+#
+# @type: parameter @CommandLineParameterType
+#
+# @help: human readable text string, not suitable for parsing.
+#
+# @default: default value string (since 2.1)
+#
+# Since: 1.5
+##
+{ 'struct': 'CommandLineParameterInfo',
+  'data': { 'name': 'str',
+            'type': 'CommandLineParameterType',
+            '*help': 'str',
+            '*default': 'str' } }
+
+##
+# @CommandLineOptionInfo:
+#
+# Details about a command line option, including its list of parameter details
+#
+# @option: option name
+#
+# @parameters: an array of @CommandLineParameterInfo
+#
+# Since: 1.5
+##
+{ 'struct': 'CommandLineOptionInfo',
+  'data': { 'option': 'str', 'parameters': ['CommandLineParameterInfo'] } }
+
+##
+# @query-command-line-options:
+#
+# Query command line option schema.
+#
+# @option: option name
+#
+# Returns: list of @CommandLineOptionInfo for all options (or for the given
+#          @option).  Returns an error if the given @option doesn't exist.
+#
+# Since: 1.5
+#
+# Example:
+#
+# -> { "execute": "query-command-line-options",
+#      "arguments": { "option": "option-rom" } }
+# <- { "return": [
+#         {
+#             "parameters": [
+#                 {
+#                     "name": "romfile",
+#                     "type": "string"
+#                 },
+#                 {
+#                     "name": "bootindex",
+#                     "type": "number"
+#                 }
+#             ],
+#             "option": "option-rom"
+#         }
+#      ]
+#    }
+#
+##
+{'command': 'query-command-line-options', 'data': { '*option': 'str' },
+ 'returns': ['CommandLineOptionInfo'] }
+
+##
+# @X86CPURegister32:
+#
+# A X86 32-bit register
+#
+# Since: 1.5
+##
+{ 'enum': 'X86CPURegister32',
+  'data': [ 'EAX', 'EBX', 'ECX', 'EDX', 'ESP', 'EBP', 'ESI', 'EDI' ] }
+
+##
+# @X86CPUFeatureWordInfo:
+#
+# Information about a X86 CPU feature word
+#
+# @cpuid-input-eax: Input EAX value for CPUID instruction for that feature word
+#
+# @cpuid-input-ecx: Input ECX value for CPUID instruction for that
+#                   feature word
+#
+# @cpuid-register: Output register containing the feature bits
+#
+# @features: value of output register, containing the feature bits
+#
+# Since: 1.5
+##
+{ 'struct': 'X86CPUFeatureWordInfo',
+  'data': { 'cpuid-input-eax': 'int',
+            '*cpuid-input-ecx': 'int',
+            'cpuid-register': 'X86CPURegister32',
+            'features': 'int' } }
+
+##
+# @DummyForceArrays:
+#
+# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally
+#
+# Since: 2.5
+##
+{ 'struct': 'DummyForceArrays',
+  'data': { 'unused': ['X86CPUFeatureWordInfo'] } }
+
+
+##
+# @NumaOptionsType:
+#
+# @node: NUMA nodes configuration
+#
+# @dist: NUMA distance configuration (since 2.10)
+#
+# @cpu: property based CPU(s) to node mapping (Since: 2.10)
+#
+# Since: 2.1
+##
+{ 'enum': 'NumaOptionsType',
+  'data': [ 'node', 'dist', 'cpu' ] }
+
+##
+# @NumaOptions:
+#
+# A discriminated record of NUMA options. (for OptsVisitor)
+#
+# Since: 2.1
+##
+{ 'union': 'NumaOptions',
+  'base': { 'type': 'NumaOptionsType' },
+  'discriminator': 'type',
+  'data': {
+    'node': 'NumaNodeOptions',
+    'dist': 'NumaDistOptions',
+    'cpu': 'NumaCpuOptions' }}
+
+##
+# @NumaNodeOptions:
+#
+# Create a guest NUMA node. (for OptsVisitor)
+#
+# @nodeid: NUMA node ID (increase by 1 from 0 if omitted)
+#
+# @cpus: VCPUs belonging to this node (assign VCPUS round-robin
+#         if omitted)
+#
+# @mem: memory size of this node; mutually exclusive with @memdev.
+#       Equally divide total memory among nodes if both @mem and @memdev are
+#       omitted.
+#
+# @memdev: memory backend object.  If specified for one node,
+#          it must be specified for all nodes.
+#
+# Since: 2.1
+##
+{ 'struct': 'NumaNodeOptions',
+  'data': {
+   '*nodeid': 'uint16',
+   '*cpus':   ['uint16'],
+   '*mem':    'size',
+   '*memdev': 'str' }}
+
+##
+# @NumaDistOptions:
+#
+# Set the distance between 2 NUMA nodes.
+#
+# @src: source NUMA node.
+#
+# @dst: destination NUMA node.
+#
+# @val: NUMA distance from source node to destination node.
+#       When a node is unreachable from another node, set the distance
+#       between them to 255.
+#
+# Since: 2.10
+##
+{ 'struct': 'NumaDistOptions',
+  'data': {
+   'src': 'uint16',
+   'dst': 'uint16',
+   'val': 'uint8' }}
+
+##
+# @NumaCpuOptions:
+#
+# Option "-numa cpu" overrides default cpu to node mapping.
+# It accepts the same set of cpu properties as returned by
+# query-hotpluggable-cpus[].props, where node-id could be used to
+# override default node mapping.
+#
+# Since: 2.10
+##
+{ 'struct': 'NumaCpuOptions',
+   'base': 'CpuInstanceProperties',
+   'data' : {} }
+
+##
+# @HostMemPolicy:
+#
+# Host memory policy types
+#
+# @default: restore default policy, remove any nondefault policy
+#
+# @preferred: set the preferred host nodes for allocation
+#
+# @bind: a strict policy that restricts memory allocation to the
+#        host nodes specified
+#
+# @interleave: memory allocations are interleaved across the set
+#              of host nodes specified
+#
+# Since: 2.1
+##
+{ 'enum': 'HostMemPolicy',
+  'data': [ 'default', 'preferred', 'bind', 'interleave' ] }
+
+##
+# @Memdev:
+#
+# Information about memory backend
+#
+# @id: backend's ID if backend has 'id' property (since 2.9)
+#
+# @size: memory backend size
+#
+# @merge: enables or disables memory merge support
+#
+# @dump: includes memory backend's memory in a core dump or not
+#
+# @prealloc: enables or disables memory preallocation
+#
+# @host-nodes: host nodes for its memory policy
+#
+# @policy: memory policy of memory backend
+#
+# Since: 2.1
+##
+{ 'struct': 'Memdev',
+  'data': {
+    '*id':        'str',
+    'size':       'size',
+    'merge':      'bool',
+    'dump':       'bool',
+    'prealloc':   'bool',
+    'host-nodes': ['uint16'],
+    'policy':     'HostMemPolicy' }}
+
+##
+# @query-memdev:
+#
+# Returns information for all memory backends.
+#
+# Returns: a list of @Memdev.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-memdev" }
+# <- { "return": [
+#        {
+#          "id": "mem1",
+#          "size": 536870912,
+#          "merge": false,
+#          "dump": true,
+#          "prealloc": false,
+#          "host-nodes": [0, 1],
+#          "policy": "bind"
+#        },
+#        {
+#          "size": 536870912,
+#          "merge": false,
+#          "dump": true,
+#          "prealloc": true,
+#          "host-nodes": [2, 3],
+#          "policy": "preferred"
+#        }
+#      ]
+#    }
+#
+##
+{ 'command': 'query-memdev', 'returns': ['Memdev'] }
+
+##
+# @PCDIMMDeviceInfo:
+#
+# PCDIMMDevice state information
+#
+# @id: device's ID
+#
+# @addr: physical address, where device is mapped
+#
+# @size: size of memory that the device provides
+#
+# @slot: slot number at which device is plugged in
+#
+# @node: NUMA node number where device is plugged in
+#
+# @memdev: memory backend linked with device
+#
+# @hotplugged: true if device was hotplugged
+#
+# @hotpluggable: true if device if could be added/removed while machine is running
+#
+# Since: 2.1
+##
+{ 'struct': 'PCDIMMDeviceInfo',
+  'data': { '*id': 'str',
+            'addr': 'int',
+            'size': 'int',
+            'slot': 'int',
+            'node': 'int',
+            'memdev': 'str',
+            'hotplugged': 'bool',
+            'hotpluggable': 'bool'
+          }
+}
+
+##
+# @MemoryDeviceInfo:
+#
+# Union containing information about a memory device
+#
+# Since: 2.1
+##
+{ 'union': 'MemoryDeviceInfo', 'data': {'dimm': 'PCDIMMDeviceInfo'} }
+
+##
+# @query-memory-devices:
+#
+# Lists available memory devices and their state
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-memory-devices" }
+# <- { "return": [ { "data":
+#                       { "addr": 5368709120,
+#                         "hotpluggable": true,
+#                         "hotplugged": true,
+#                         "id": "d1",
+#                         "memdev": "/objects/memX",
+#                         "node": 0,
+#                         "size": 1073741824,
+#                         "slot": 0},
+#                    "type": "dimm"
+#                  } ] }
+#
+##
+{ 'command': 'query-memory-devices', 'returns': ['MemoryDeviceInfo'] }
+
+##
+# @MEM_UNPLUG_ERROR:
+#
+# Emitted when memory hot unplug error occurs.
+#
+# @device: device name
+#
+# @msg: Informative message
+#
+# Since: 2.4
+#
+# Example:
+#
+# <- { "event": "MEM_UNPLUG_ERROR"
+#      "data": { "device": "dimm1",
+#                "msg": "acpi: device unplug for unsupported device"
+#      },
+#      "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+#
+##
+{ 'event': 'MEM_UNPLUG_ERROR',
+  'data': { 'device': 'str', 'msg': 'str' } }
+
+##
+# @ACPISlotType:
+#
+# @DIMM: memory slot
+# @CPU: logical CPU slot (since 2.7)
+##
+{ 'enum': 'ACPISlotType', 'data': [ 'DIMM', 'CPU' ] }
+
+##
+# @ACPIOSTInfo:
+#
+# OSPM Status Indication for a device
+# For description of possible values of @source and @status fields
+# see "_OST (OSPM Status Indication)" chapter of ACPI5.0 spec.
+#
+# @device: device ID associated with slot
+#
+# @slot: slot ID, unique per slot of a given @slot-type
+#
+# @slot-type: type of the slot
+#
+# @source: an integer containing the source event
+#
+# @status: an integer containing the status code
+#
+# Since: 2.1
+##
+{ 'struct': 'ACPIOSTInfo',
+  'data'  : { '*device': 'str',
+              'slot': 'str',
+              'slot-type': 'ACPISlotType',
+              'source': 'int',
+              'status': 'int' } }
+
+##
+# @query-acpi-ospm-status:
+#
+# Return a list of ACPIOSTInfo for devices that support status
+# reporting via ACPI _OST method.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "query-acpi-ospm-status" }
+# <- { "return": [ { "device": "d1", "slot": "0", "slot-type": "DIMM", "source": 1, "status": 0},
+#                  { "slot": "1", "slot-type": "DIMM", "source": 0, "status": 0},
+#                  { "slot": "2", "slot-type": "DIMM", "source": 0, "status": 0},
+#                  { "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0}
+#    ]}
+#
+##
+{ 'command': 'query-acpi-ospm-status', 'returns': ['ACPIOSTInfo'] }
+
+##
+# @ACPI_DEVICE_OST:
+#
+# Emitted when guest executes ACPI _OST method.
+#
+# @info: ACPIOSTInfo type as described in qapi-schema.json
+#
+# Since: 2.1
+#
+# Example:
+#
+# <- { "event": "ACPI_DEVICE_OST",
+#      "data": { "device": "d1", "slot": "0",
+#                "slot-type": "DIMM", "source": 1, "status": 0 } }
+#
+##
+{ 'event': 'ACPI_DEVICE_OST',
+     'data': { 'info': 'ACPIOSTInfo' } }
+
+##
+# @rtc-reset-reinjection:
+#
+# This command will reset the RTC interrupt reinjection backlog.
+# Can be used if another mechanism to synchronize guest time
+# is in effect, for example QEMU guest agent's guest-set-time
+# command.
+#
+# Since: 2.1
+#
+# Example:
+#
+# -> { "execute": "rtc-reset-reinjection" }
+# <- { "return": {} }
+#
+##
+{ 'command': 'rtc-reset-reinjection' }
+
+##
+# @RTC_CHANGE:
+#
+# Emitted when the guest changes the RTC time.
+#
+# @offset: offset between base RTC clock (as specified by -rtc base), and
+#          new RTC clock value
+#
+# Note: This event is rate-limited.
+#
+# Since: 0.13.0
+#
+# Example:
+#
+# <-   { "event": "RTC_CHANGE",
+#        "data": { "offset": 78 },
+#        "timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
+#
+##
+{ 'event': 'RTC_CHANGE',
+  'data': { 'offset': 'int' } }
+
+##
+# @ReplayMode:
+#
+# Mode of the replay subsystem.
+#
+# @none: normal execution mode. Replay or record are not enabled.
+#
+# @record: record mode. All non-deterministic data is written into the
+#          replay log.
+#
+# @play: replay mode. Non-deterministic data required for system execution
+#        is read from the log.
+#
+# Since: 2.5
+##
+{ 'enum': 'ReplayMode',
+  'data': [ 'none', 'record', 'play' ] }
+
+##
+# @xen-load-devices-state:
+#
+# Load the state of all devices from file. The RAM and the block devices
+# of the VM are not loaded by this command.
+#
+# @filename: the file to load the state of the devices from as binary
+# data. See xen-save-devices-state.txt for a description of the binary
+# format.
+#
+# Since: 2.7
+#
+# Example:
+#
+# -> { "execute": "xen-load-devices-state",
+#      "arguments": { "filename": "/tmp/resume" } }
+# <- { "return": {} }
+#
+##
+{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} }
+
+##
+# @GICCapability:
+#
+# The struct describes capability for a specific GIC (Generic
+# Interrupt Controller) version. These bits are not only decided by
+# QEMU/KVM software version, but also decided by the hardware that
+# the program is running upon.
+#
+# @version:  version of GIC to be described. Currently, only 2 and 3
+#            are supported.
+#
+# @emulated: whether current QEMU/hardware supports emulated GIC
+#            device in user space.
+#
+# @kernel:   whether current QEMU/hardware supports hardware
+#            accelerated GIC device in kernel.
+#
+# Since: 2.6
+##
+{ 'struct': 'GICCapability',
+  'data': { 'version': 'int',
+            'emulated': 'bool',
+            'kernel': 'bool' } }
+
+##
+# @query-gic-capabilities:
+#
+# This command is ARM-only. It will return a list of GICCapability
+# objects that describe its capability bits.
+#
+# Returns: a list of GICCapability objects.
+#
+# Since: 2.6
+#
+# Example:
+#
+# -> { "execute": "query-gic-capabilities" }
+# <- { "return": [{ "version": 2, "emulated": true, "kernel": false },
+#                 { "version": 3, "emulated": false, "kernel": true } ] }
+#
+##
+{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'] }
+
+##
+# @CpuInstanceProperties:
+#
+# List of properties to be used for hotplugging a CPU instance,
+# it should be passed by management with device_add command when
+# a CPU is being hotplugged.
+#
+# @node-id: NUMA node ID the CPU belongs to
+# @socket-id: socket number within node/board the CPU belongs to
+# @core-id: core number within socket the CPU belongs to
+# @thread-id: thread number within core the CPU belongs to
+#
+# Note: currently there are 4 properties that could be present
+# but management should be prepared to pass through other
+# properties with device_add command to allow for future
+# interface extension. This also requires the filed names to be kept in
+# sync with the properties passed to -device/device_add.
+#
+# Since: 2.7
+##
+{ 'struct': 'CpuInstanceProperties',
+  'data': { '*node-id': 'int',
+            '*socket-id': 'int',
+            '*core-id': 'int',
+            '*thread-id': 'int'
+  }
+}
+
+##
+# @HotpluggableCPU:
+#
+# @type: CPU object type for usage with device_add command
+# @props: list of properties to be used for hotplugging CPU
+# @vcpus-count: number of logical VCPU threads @HotpluggableCPU provides
+# @qom-path: link to existing CPU object if CPU is present or
+#            omitted if CPU is not present.
+#
+# Since: 2.7
+##
+{ 'struct': 'HotpluggableCPU',
+  'data': { 'type': 'str',
+            'vcpus-count': 'int',
+            'props': 'CpuInstanceProperties',
+            '*qom-path': 'str'
+          }
+}
+
+##
+# @query-hotpluggable-cpus:
+#
+# Returns: a list of HotpluggableCPU objects.
+#
+# Since: 2.7
+#
+# Example:
+#
+# For pseries machine type started with -smp 2,cores=2,maxcpus=4 -cpu POWER8:
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+#      { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core",
+#        "vcpus-count": 1 },
+#      { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core",
+#        "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"}
+#    ]}'
+#
+# For pc machine type started with -smp 1,maxcpus=2:
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+#      {
+#         "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
+#         "props": {"core-id": 0, "socket-id": 1, "thread-id": 0}
+#      },
+#      {
+#         "qom-path": "/machine/unattached/device[0]",
+#         "type": "qemu64-x86_64-cpu", "vcpus-count": 1,
+#         "props": {"core-id": 0, "socket-id": 0, "thread-id": 0}
+#      }
+#    ]}
+#
+# For s390x-virtio-ccw machine type started with -smp 1,maxcpus=2 -cpu qemu
+# (Since: 2.11):
+#
+# -> { "execute": "query-hotpluggable-cpus" }
+# <- {"return": [
+#      {
+#         "type": "qemu-s390x-cpu", "vcpus-count": 1,
+#         "props": { "core-id": 1 }
+#      },
+#      {
+#         "qom-path": "/machine/unattached/device[0]",
+#         "type": "qemu-s390x-cpu", "vcpus-count": 1,
+#         "props": { "core-id": 0 }
+#      }
+#    ]}
+#
+##
+{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'] }
+
+##
+# @GuidInfo:
+#
+# GUID information.
+#
+# @guid: the globally unique identifier
+#
+# Since: 2.9
+##
+{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} }
+
+##
+# @query-vm-generation-id:
+#
+# Show Virtual Machine Generation ID
+#
+# Since: 2.9
+##
+{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index bca46a8785..a27c3c2a93 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -283,6 +283,16 @@
   'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
             'inject-nmi' ] }
 
+
+##
+# @watchdog-set-action:
+#
+# Set watchdog action
+#
+# Since: 2.11
+##
+{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
 ##
 # @GUEST_PANICKED:
 #
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 846238175f..b8f6bc3f7e 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -22,9 +22,9 @@
 #include "hw/sysbus.h"
 #include "monitor/monitor.h"
 #include "monitor/qdev.h"
-#include "qmp-commands.h"
 #include "sysemu/arch_init.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/config-file.h"
diff --git a/qmp.c b/qmp.c
index 793f6f3323..a8d4eba973 100644
--- a/qmp.c
+++ b/qmp.c
@@ -21,7 +21,6 @@
 #include "sysemu/sysemu.h"
 #include "qemu/config-file.h"
 #include "qemu/uuid.h"
-#include "qmp-commands.h"
 #include "chardev/char.h"
 #include "ui/qemu-spice.h"
 #include "ui/vnc.h"
@@ -32,6 +31,9 @@
 #include "sysemu/block-backend.h"
 #include "qom/qom-qobject.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qobject-input-visitor.h"
diff --git a/stubs/uuid.c b/stubs/uuid.c
index a880de8d61..a802e9836b 100644
--- a/stubs/uuid.c
+++ b/stubs/uuid.c
@@ -1,7 +1,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/uuid.h"
-#include "qmp-commands.h"
 
 UuidInfo *qmp_query_uuid(Error **errp)
 {
diff --git a/stubs/vmgenid.c b/stubs/vmgenid.c
index 3c8fe55bdf..568e42b064 100644
--- a/stubs/vmgenid.c
+++ b/stubs/vmgenid.c
@@ -1,6 +1,6 @@
 #include "qemu/osdep.h"
-#include "qmp-commands.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qerror.h"
 
 GuidInfo *qmp_query_vm_generation_id(Error **errp)
diff --git a/stubs/xen-hvm.c b/stubs/xen-hvm.c
index 3ca6c51b21..0067bcc6db 100644
--- a/stubs/xen-hvm.c
+++ b/stubs/xen-hvm.c
@@ -12,7 +12,7 @@
 #include "qemu-common.h"
 #include "hw/xen/xen.h"
 #include "exec/memory.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands-misc.h"
 
 int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
 {
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 299cb80ae7..4cdd2676dd 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -19,10 +19,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #include "qemu/osdep.h"
-#include "qmp-commands.h"
 #include "hw/boards.h"
 #include "kvm_arm.h"
+#include "qapi/qapi-commands-misc.h"
 
 static GICCapability *gic_cap_new(int version)
 {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index b5e431e769..2c04645cea 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -31,10 +31,10 @@
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-misc.h"
+#include "qapi/qapi-visit-run-state.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
-
-#include "qapi-visit.h"
 #include "qapi/visitor.h"
 #include "qom/qom-qobject.h"
 #include "sysemu/arch_init.h"
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 908f9b981f..8c1a997da4 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -12,8 +12,9 @@
 
 #include "qemu/osdep.h"
 #include "libqtest.h"
-#include "qapi-visit.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-introspect.h"
+#include "qapi/qapi-visit-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qlist.h"
 #include "qapi/qobject-input-visitor.h"
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 3900be2610..d3a56bd071 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -15,6 +15,7 @@
 
 #include "qemu-common.h"
 #include "qapi/error.h"
+#include "qapi/qapi-visit-introspect.h"
 #include "qapi/qobject-input-visitor.h"
 #include "test-qapi-visit.h"
 #include "qapi/qmp/qbool.h"
@@ -25,7 +26,6 @@
 #include "qapi/qmp/qjson.h"
 #include "test-qmp-introspect.h"
 #include "qmp-introspect.h"
-#include "qapi-visit.h"
 
 typedef struct TestInputVisitorData {
     QObject *obj;
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index dd7e51d4f5..438c18a0d6 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -23,7 +23,6 @@
 #include "qapi/qobject-output-visitor.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/string-output-visitor.h"
-#include "qapi-visit.h"
 #include "qapi/dealloc-visitor.h"
 
 enum PrimitiveTypeKind {
diff --git a/ui/gtk.c b/ui/gtk.c
index 1537751afa..a82494d605 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -37,6 +37,7 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qemu/cutils.h"
 
 #include "ui/console.h"
@@ -52,7 +53,6 @@
 #include "trace.h"
 #include "ui/input.h"
 #include "sysemu/sysemu.h"
-#include "qmp-commands.h"
 #include "keymaps.h"
 #include "chardev/char.h"
 #include "qom/object.h"
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 10cae120cc..c651c4826e 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -1,12 +1,12 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qlist.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
-#include "qmp-commands.h"
 
 static QemuOptsList *vm_config_groups[48];
 static QemuOptsList *drive_config_groups[5];
diff --git a/vl.c b/vl.c
index 4e8287c507..4c8fb37bee 100644
--- a/vl.c
+++ b/vl.c
@@ -100,7 +100,6 @@ int main(int argc, char **argv)
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qemu-options.h"
-#include "qmp-commands.h"
 #include "qemu/main-loop.h"
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
@@ -126,6 +125,9 @@ int main(int argc, char **argv)
 #include "sysemu/replay.h"
 #include "qapi/qapi-events-run-state.h"
 #include "qapi/qapi-visit-block-core.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-run-state.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/iothread.h"
 
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (23 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:27   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
                   ` (6 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

With modular code generation, putting stuff right into
qapi-schema.json is a bad idea.  Update writing-qmp-commands.txt
accordingly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/devel/writing-qmp-commands.txt | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
index 4f5b24c0c4..776b3b41ca 100644
--- a/docs/devel/writing-qmp-commands.txt
+++ b/docs/devel/writing-qmp-commands.txt
@@ -15,8 +15,8 @@ start with docs/interop/qmp-intro.txt.
 Generally speaking, the following steps should be taken in order to write a
 new QMP command.
 
-1. Write the command's and type(s) specification in the QAPI schema file
-   (qapi-schema.json in the root source directory)
+1. Define the command and any types it needs in the appropriate QAPI
+   schema module.
 
 2. Write the QMP command itself, which is a regular C function. Preferably,
    the command should be exported by some QEMU subsystem. But it can also be
@@ -88,8 +88,9 @@ command carries some meaningful action in QEMU but here it will just print
 Our command will be called "hello-world". It takes no arguments, nor does it
 return any data.
 
-The first step is to add the following line to the bottom of the
-qapi-schema.json file:
+The first step is defining the command in the appropriate QAPI schema
+module.  We pick module qapi/misc.json, and add the following line at
+the bottom:
 
 { 'command': 'hello-world' }
 
@@ -245,7 +246,7 @@ This is very important. No QMP command will be accepted in QEMU without proper
 documentation.
 
 There are many examples of such documentation in the schema file already, but
-here goes "hello-world"'s new entry for the qapi-schema.json file:
+here goes "hello-world"'s new entry for qapi/misc.json:
 
 ##
 # @hello-world
@@ -425,8 +426,7 @@ There are a number of things to be noticed:
    allocated by the implementation. This is so because the QAPI also generates
    a function to free its types and it cannot distinguish between dynamically
    or statically allocated strings
-6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
-   otherwise qemu won't build
+6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
 
 Time to test the new command. Build qemu, run it as described in the "Testing"
 section and try this:
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (24 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:29   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
                   ` (5 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

* Fix guidance on error classes

* Point to generated documentation

* Drop plea for documentation, because the QAPI code generator
  enforces it since commit 3313b6124b

* Minor tweaks here and there

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/devel/writing-qmp-commands.txt | 25 +++++++++----------------
 docs/interop/qmp-intro.txt          |  3 ++-
 2 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
index 776b3b41ca..50385eff27 100644
--- a/docs/devel/writing-qmp-commands.txt
+++ b/docs/devel/writing-qmp-commands.txt
@@ -36,9 +36,9 @@ very simple and get more complex as we progress.
 For all the examples in the next sections, the test setup is the same and is
 shown here.
 
-First, QEMU should be started as:
+First, QEMU should be started like this:
 
-# /path/to/your/source/qemu [...] \
+# qemu-system-TARGET [...] \
     -chardev socket,id=qmp,port=4444,host=localhost,server \
     -mon chardev=qmp,mode=control,pretty=on
 
@@ -179,7 +179,7 @@ described in the "Testing" section and then send two commands:
     }
 }
 
-You should see "Hello, world" and "we love qemu" in the terminal running qemu,
+You should see "Hello, world" and "We love qemu" in the terminal running qemu,
 if you don't see these strings, then something went wrong.
 
 === Errors ===
@@ -221,30 +221,23 @@ The QMP server's response should be:
     }
 }
 
-As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR
-(done by default when using error_setg()). There are two exceptions to
-this rule:
+Note that error_setg() produces a "GenericError" class.  In general,
+all QMP errors should have that error class.  There are two exceptions
+to this rule:
 
- 1. A non-generic ErrorClass value exists* for the failure you want to report
-    (eg. DeviceNotFound)
+ 1. To support a management application's need to recognize a specific
+    error for special handling
 
- 2. Management applications have to take special action on the failure you
-    want to report, hence you have to add a new ErrorClass value so that they
-    can check for it
+ 2. Backward compatibility
 
 If the failure you want to report falls into one of the two cases above,
 use error_set() with a second argument of an ErrorClass value.
 
- * All existing ErrorClass values are defined in the qapi-schema.json file
-
 === Command Documentation ===
 
 There's only one step missing to make "hello-world"'s implementation complete,
 and that's its documentation in the schema file.
 
-This is very important. No QMP command will be accepted in QEMU without proper
-documentation.
-
 There are many examples of such documentation in the schema file already, but
 here goes "hello-world"'s new entry for qapi/misc.json:
 
diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
index adbc94abb1..430fe1b747 100644
--- a/docs/interop/qmp-intro.txt
+++ b/docs/interop/qmp-intro.txt
@@ -78,7 +78,8 @@ Escape character is '^]'.
     }
 }
 
-Please, refer to the qapi-schema.json file for a complete command reference.
+Please refer to docs/interop/qemu-qmp-ref.* for a complete command
+reference, generated from qapi-schema.json.
 
 QMP wiki page
 -------------
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (25 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:36   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
                   ` (4 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Move qapi-schema.json to qapi/, so it's next to its modules, and all
files get generated to qapi/, not just the ones generated for modules.

Consistently name the generated files qapi-MODULE.EXT:
qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become
qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch].
This gets rid of the temporary hacks in scripts/qapi/commands.py and
scripts/qapi/events.py.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore                                | 16 ++++++------
 Makefile                                  | 42 +++++++++++++++----------------
 Makefile.objs                             | 21 ++++++++--------
 backends/hostmem.c                        |  2 +-
 docs/devel/qapi-code-gen.txt              | 30 +++++++++++-----------
 docs/devel/writing-qmp-commands.txt       |  2 +-
 docs/interop/qmp-intro.txt                |  2 +-
 hmp.c                                     |  2 +-
 include/qapi/qmp/qobject.h                |  2 +-
 include/qapi/visitor.h                    |  2 +-
 include/qom/object.h                      |  2 +-
 monitor.c                                 |  6 ++---
 net/filter-buffer.c                       |  2 +-
 qapi/misc.json                            |  4 +--
 qapi-schema.json => qapi/qapi-schema.json | 32 +++++++++++------------
 qga/Makefile.objs                         |  2 +-
 qga/commands-posix.c                      |  2 +-
 qga/commands-win32.c                      |  2 +-
 qga/commands.c                            |  2 +-
 qga/main.c                                |  2 +-
 qom/object.c                              |  2 +-
 scripts/qapi/commands.py                  |  7 ------
 scripts/qapi/events.py                    |  9 +------
 scripts/qapi/introspect.py                |  4 +--
 scripts/qapi/types.py                     |  6 ++---
 scripts/qapi/visit.py                     |  6 ++---
 tests/.gitignore                          |  6 ++---
 tests/Makefile.include                    | 14 +++++------
 tests/test-qmp-cmds.c                     |  2 +-
 tests/test-qmp-event.c                    |  2 +-
 tests/test-qobject-input-visitor.c        |  6 ++---
 tpm.c                                     |  1 -
 ui/cocoa.m                                |  2 +-
 ui/vnc.c                                  |  2 +-
 34 files changed, 116 insertions(+), 130 deletions(-)
 rename qapi-schema.json => qapi/qapi-schema.json (85%)

diff --git a/.gitignore b/.gitignore
index 7f162e862f..dabfe6bea8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,8 +29,8 @@
 /qga/qapi-generated
 /qapi-generated
 /qapi-gen-timestamp
-/qapi-builtin-types.[ch]
-/qapi-builtin-visit.[ch]
+/qapi/qapi-builtin-types.[ch]
+/qapi/qapi-builtin-visit.[ch]
 /qapi/qapi-commands-block-core.[ch]
 /qapi/qapi-commands-block.[ch]
 /qapi/qapi-commands-char.[ch]
@@ -47,6 +47,7 @@
 /qapi/qapi-commands-trace.[ch]
 /qapi/qapi-commands-transaction.[ch]
 /qapi/qapi-commands-ui.[ch]
+/qapi/qapi-commands.[ch]
 /qapi/qapi-events-block-core.[ch]
 /qapi/qapi-events-block.[ch]
 /qapi/qapi-events-char.[ch]
@@ -63,6 +64,8 @@
 /qapi/qapi-events-trace.[ch]
 /qapi/qapi-events-transaction.[ch]
 /qapi/qapi-events-ui.[ch]
+/qapi/qapi-events.[ch]
+/qapi/qapi-introspect.[ch]
 /qapi/qapi-types-block-core.[ch]
 /qapi/qapi-types-block.[ch]
 /qapi/qapi-types-char.[ch]
@@ -79,7 +82,7 @@
 /qapi/qapi-types-trace.[ch]
 /qapi/qapi-types-transaction.[ch]
 /qapi/qapi-types-ui.[ch]
-/qapi-types.[ch]
+/qapi/qapi-types.[ch]
 /qapi/qapi-visit-block-core.[ch]
 /qapi/qapi-visit-block.[ch]
 /qapi/qapi-visit-char.[ch]
@@ -96,11 +99,8 @@
 /qapi/qapi-visit-trace.[ch]
 /qapi/qapi-visit-transaction.[ch]
 /qapi/qapi-visit-ui.[ch]
-/qapi-visit.[ch]
-/qapi-event.[ch]
-/qapi-doc.texi
-/qmp-commands.[ch]
-/qmp-introspect.[ch]
+/qapi/qapi-visit.[ch]
+/qapi/qapi-doc.texi
 /qemu-doc.html
 /qemu-doc.info
 /qemu-doc.txt
diff --git a/Makefile b/Makefile
index 50eb194877..84411ee6ab 100644
--- a/Makefile
+++ b/Makefile
@@ -90,8 +90,8 @@ endif
 include $(SRC_PATH)/rules.mak
 
 GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
-GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
-GENERATED_FILES += qapi-types.h qapi-types.c
+GENERATED_FILES += qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
+GENERATED_FILES += qapi/qapi-types.h qapi/qapi-types.c
 GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
 GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c
 GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c
@@ -108,8 +108,8 @@ GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c
 GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c
 GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c
 GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c
-GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
-GENERATED_FILES += qapi-visit.h qapi-visit.c
+GENERATED_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c
+GENERATED_FILES += qapi/qapi-visit.h qapi/qapi-visit.c
 GENERATED_FILES += qapi/qapi-visit-block-core.h qapi/qapi-visit-block-core.c
 GENERATED_FILES += qapi/qapi-visit-block.h qapi/qapi-visit-block.c
 GENERATED_FILES += qapi/qapi-visit-char.h qapi/qapi-visit-char.c
@@ -126,7 +126,7 @@ GENERATED_FILES += qapi/qapi-visit-tpm.h qapi/qapi-visit-tpm.c
 GENERATED_FILES += qapi/qapi-visit-trace.h qapi/qapi-visit-trace.c
 GENERATED_FILES += qapi/qapi-visit-transaction.h qapi/qapi-visit-transaction.c
 GENERATED_FILES += qapi/qapi-visit-ui.h qapi/qapi-visit-ui.c
-GENERATED_FILES += qmp-commands.h qmp-commands.c
+GENERATED_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
 GENERATED_FILES += qapi/qapi-commands-block-core.h qapi/qapi-commands-block-core.c
 GENERATED_FILES += qapi/qapi-commands-block.h qapi/qapi-commands-block.c
 GENERATED_FILES += qapi/qapi-commands-char.h qapi/qapi-commands-char.c
@@ -143,7 +143,7 @@ GENERATED_FILES += qapi/qapi-commands-tpm.h qapi/qapi-commands-tpm.c
 GENERATED_FILES += qapi/qapi-commands-trace.h qapi/qapi-commands-trace.c
 GENERATED_FILES += qapi/qapi-commands-transaction.h qapi/qapi-commands-transaction.c
 GENERATED_FILES += qapi/qapi-commands-ui.h qapi/qapi-commands-ui.c
-GENERATED_FILES += qapi-event.h qapi-event.c
+GENERATED_FILES += qapi/qapi-events.h qapi/qapi-events.c
 GENERATED_FILES += qapi/qapi-events-block-core.h qapi/qapi-events-block-core.c
 GENERATED_FILES += qapi/qapi-events-block.h qapi/qapi-events-block.c
 GENERATED_FILES += qapi/qapi-events-char.h qapi/qapi-events-char.c
@@ -160,8 +160,8 @@ GENERATED_FILES += qapi/qapi-events-tpm.h qapi/qapi-events-tpm.c
 GENERATED_FILES += qapi/qapi-events-trace.h qapi/qapi-events-trace.c
 GENERATED_FILES += qapi/qapi-events-transaction.h qapi/qapi-events-transaction.c
 GENERATED_FILES += qapi/qapi-events-ui.h qapi/qapi-events-ui.c
-GENERATED_FILES += qmp-introspect.c qmp-introspect.h
-GENERATED_FILES += qapi-doc.texi
+GENERATED_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
+GENERATED_FILES += qapi/qapi-doc.texi
 
 GENERATED_FILES += trace/generated-tcg-tracers.h
 
@@ -563,7 +563,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
 
 qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
 qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
-qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
+qga/qapi-generated/qga-qapi-commands.h qga/qapi-generated/qga-qapi-commands.c \
 qga/qapi-generated/qga-qapi-doc.texi: \
 qga/qapi-generated/qapi-gen-timestamp ;
 qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
@@ -572,7 +572,7 @@ qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-p
 		"GEN","$(@:%-timestamp=%)")
 	@>$@
 
-qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
+qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
                $(SRC_PATH)/qapi/char.json \
                $(SRC_PATH)/qapi/crypto.json \
@@ -588,8 +588,8 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/transaction.json \
                $(SRC_PATH)/qapi/ui.json
 
-qapi-builtin-types.c qapi-builtin-types.h \
-qapi-types.c qapi-types.h \
+qapi/qapi-builtin-types.c qapi/qapi-builtin-types.h \
+qapi/qapi-types.c qapi/qapi-types.h \
 qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
 qapi/qapi-types-block.c qapi/qapi-types-block.h \
 qapi/qapi-types-char.c qapi/qapi-types-char.h \
@@ -606,8 +606,8 @@ qapi/qapi-types-tpm.c qapi/qapi-types-tpm.h \
 qapi/qapi-types-trace.c qapi/qapi-types-trace.h \
 qapi/qapi-types-transaction.c qapi/qapi-types-transaction.h \
 qapi/qapi-types-ui.c qapi/qapi-types-ui.h \
-qapi-builtin-visit.c qapi-builtin-visit.h \
-qapi-visit.c qapi-visit.h \
+qapi/qapi-builtin-visit.c qapi/qapi-builtin-visit.h \
+qapi/qapi-visit.c qapi/qapi-visit.h \
 qapi/qapi-visit-block-core.c qapi/qapi-visit-block-core.h \
 qapi/qapi-visit-block.c qapi/qapi-visit-block.h \
 qapi/qapi-visit-char.c qapi/qapi-visit-char.h \
@@ -624,7 +624,7 @@ qapi/qapi-visit-tpm.c qapi/qapi-visit-tpm.h \
 qapi/qapi-visit-trace.c qapi/qapi-visit-trace.h \
 qapi/qapi-visit-transaction.c qapi/qapi-visit-transaction.h \
 qapi/qapi-visit-ui.c qapi/qapi-visit-ui.h \
-qmp-commands.h qmp-commands.c \
+qapi/qapi-commands.h qapi/qapi-commands.c \
 qapi/qapi-commands-block-core.c qapi/qapi-commands-block-core.h \
 qapi/qapi-commands-block.c qapi/qapi-commands-block.h \
 qapi/qapi-commands-char.c qapi/qapi-commands-char.h \
@@ -641,7 +641,7 @@ qapi/qapi-commands-tpm.c qapi/qapi-commands-tpm.h \
 qapi/qapi-commands-trace.c qapi/qapi-commands-trace.h \
 qapi/qapi-commands-transaction.c qapi/qapi-commands-transaction.h \
 qapi/qapi-commands-ui.c qapi/qapi-commands-ui.h \
-qapi-event.c qapi-event.h \
+qapi/qapi-events.c qapi/qapi-events.h \
 qapi/qapi-events-block-core.c qapi/qapi-events-block-core.h \
 qapi/qapi-events-block.c qapi/qapi-events-block.h \
 qapi/qapi-events-char.c qapi/qapi-events-char.h \
@@ -658,16 +658,16 @@ qapi/qapi-events-tpm.c qapi/qapi-events-tpm.h \
 qapi/qapi-events-trace.c qapi/qapi-events-trace.h \
 qapi/qapi-events-transaction.c qapi/qapi-events-transaction.h \
 qapi/qapi-events-ui.c qapi/qapi-events-ui.h \
-qmp-introspect.h qmp-introspect.c \
-qapi-doc.texi: \
+qapi/qapi-introspect.h qapi/qapi-introspect.c \
+qapi/qapi-doc.texi: \
 qapi-gen-timestamp ;
 qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
 	$(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
-		-o "." -b $<, \
+		-o "qapi" -b $<, \
 		"GEN","$(@:%-timestamp=%)")
 	@>$@
 
-QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
+QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h)
 $(qga-obj-y): $(QGALIB_GEN)
 
 qemu-ga$(EXESUF): $(qga-obj-y) $(COMMON_LDADDS)
@@ -934,7 +934,7 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
 
-docs/interop/qemu-qmp-qapi.texi: qapi-doc.texi
+docs/interop/qemu-qmp-qapi.texi: qapi/qapi-doc.texi
 	@cp -p $< $@
 
 docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi
diff --git a/Makefile.objs b/Makefile.objs
index a7986bbf0b..9aa1024c34 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -2,8 +2,8 @@
 # Common libraries for tools and emulators
 stub-obj-y = stubs/ crypto/
 util-obj-y = util/ qobject/ qapi/
-util-obj-y += qapi-builtin-types.o
-util-obj-y += qapi-types.o
+util-obj-y += qapi/qapi-builtin-types.o
+util-obj-y += qapi/qapi-types.o
 util-obj-y += qapi/qapi-types-block-core.o
 util-obj-y += qapi/qapi-types-block.o
 util-obj-y += qapi/qapi-types-char.o
@@ -20,8 +20,8 @@ util-obj-y += qapi/qapi-types-tpm.o
 util-obj-y += qapi/qapi-types-trace.o
 util-obj-y += qapi/qapi-types-transaction.o
 util-obj-y += qapi/qapi-types-ui.o
-util-obj-y += qapi-builtin-visit.o
-util-obj-y += qapi-visit.o
+util-obj-y += qapi/qapi-builtin-visit.o
+util-obj-y += qapi/qapi-visit.o
 util-obj-y += qapi/qapi-visit-block-core.o
 util-obj-y += qapi/qapi-visit-block.o
 util-obj-y += qapi/qapi-visit-char.o
@@ -38,7 +38,7 @@ util-obj-y += qapi/qapi-visit-tpm.o
 util-obj-y += qapi/qapi-visit-trace.o
 util-obj-y += qapi/qapi-visit-transaction.o
 util-obj-y += qapi/qapi-visit-ui.o
-util-obj-y += qapi-event.o
+util-obj-y += qapi/qapi-events.o
 util-obj-y += qapi/qapi-events-block-core.o
 util-obj-y += qapi/qapi-events-block.o
 util-obj-y += qapi/qapi-events-char.o
@@ -55,7 +55,7 @@ util-obj-y += qapi/qapi-events-tpm.o
 util-obj-y += qapi/qapi-events-trace.o
 util-obj-y += qapi/qapi-events-transaction.o
 util-obj-y += qapi/qapi-events-ui.o
-util-obj-y += qmp-introspect.o
+util-obj-y += qapi/qapi-introspect.o
 
 chardev-obj-y = chardev/
 
@@ -131,7 +131,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
 ######################################################################
 # qapi
 
-common-obj-y += qmp-commands.o
+common-obj-y += qapi/qapi-commands.o
 common-obj-y += qapi/qapi-commands-block-core.o
 common-obj-y += qapi/qapi-commands-block.o
 common-obj-y += qapi/qapi-commands-char.o
@@ -148,7 +148,7 @@ common-obj-y += qapi/qapi-commands-tpm.o
 common-obj-y += qapi/qapi-commands-trace.o
 common-obj-y += qapi/qapi-commands-transaction.o
 common-obj-y += qapi/qapi-commands-ui.o
-common-obj-y += qmp-introspect.o
+common-obj-y += qapi/qapi-introspect.o
 common-obj-y += qmp.o hmp.o
 endif
 
@@ -171,8 +171,9 @@ target-obj-y += trace/
 ######################################################################
 # guest agent
 
-# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
-# by libqemuutil.a.  These should be moved to a separate .json schema.
+# FIXME: a few definitions from qapi/qapi-types.o and
+# qapi/qapi-visit.o are needed by libqemuutil.a.  These should be
+# extracted into a QAPI schema module, or perhaps a separate schema.
 qga-obj-y = qga/
 qga-vss-dll-obj-y = qga/
 
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 0afaf7160a..1292a9da1e 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -14,7 +14,7 @@
 #include "sysemu/hostmem.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 #include "qapi/visitor.h"
 #include "qemu/config-file.h"
 #include "qom/object_interfaces.h"
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index ba1dc73298..0c4fc342fe 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -647,7 +647,7 @@ name an event 'MAX', since the generator also produces a C enumeration
 of all event names with a generated _MAX value at the end.  When
 'data' is also specified, additional info will be included in the
 event, with similar semantics to a 'struct' expression.  Finally there
-will be C API generated in qapi-event.h; when called by QEMU code, a
+will be C API generated in qapi-events.h; when called by QEMU code, a
 message with timestamp will be emitted on the wire.
 
 An example event is:
@@ -1147,15 +1147,15 @@ declares qmp_COMMAND() that the user must implement.
 
 The following files are generated:
 
-$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
-                         QMP command defined in the schema
+$(prefix)qapi-commands.c: Command marshal/dispatch functions for each
+                          QMP command defined in the schema
 
-$(prefix)qmp-commands.h: Function prototypes for the QMP commands
-                         specified in the schema
+$(prefix)qapi-commands.h: Function prototypes for the QMP commands
+                          specified in the schema
 
 Example:
 
-    $ cat qapi-generated/example-qmp-commands.h
+    $ cat qapi-generated/example-qapi-commands.h
 [Uninteresting stuff omitted...]
 
     #ifndef EXAMPLE_QMP_COMMANDS_H
@@ -1170,7 +1170,7 @@ Example:
     void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
 
     #endif
-    $ cat qapi-generated/example-qmp-commands.c
+    $ cat qapi-generated/example-qapi-commands.c
 [Uninteresting stuff omitted...]
 
     static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
@@ -1243,14 +1243,14 @@ qapi_event_send_EVENT().
 
 The following files are created:
 
-$(prefix)qapi-event.h - Function prototypes for each event type, plus an
+$(prefix)qapi-events.h - Function prototypes for each event type, plus an
                         enumeration of all event names
 
-$(prefix)qapi-event.c - Implementation of functions to send an event
+$(prefix)qapi-events.c - Implementation of functions to send an event
 
 Example:
 
-    $ cat qapi-generated/example-qapi-event.h
+    $ cat qapi-generated/example-qapi-events.h
 [Uninteresting stuff omitted...]
 
     #ifndef EXAMPLE_QAPI_EVENT_H
@@ -1273,7 +1273,7 @@ Example:
     extern const char *const example_QAPIEvent_lookup[];
 
     #endif
-    $ cat qapi-generated/example-qapi-event.c
+    $ cat qapi-generated/example-qapi-events.c
 [Uninteresting stuff omitted...]
 
     void qapi_event_send_my_event(Error **errp)
@@ -1305,14 +1305,14 @@ Example:
 
 The following files are created:
 
-$(prefix)qmp-introspect.c - Defines a string holding a JSON
+$(prefix)qapi-introspect.c - Defines a string holding a JSON
                             description of the schema
 
-$(prefix)qmp-introspect.h - Declares the above string
+$(prefix)qapi-introspect.h - Declares the above string
 
 Example:
 
-    $ cat qapi-generated/example-qmp-introspect.h
+    $ cat qapi-generated/example-qapi-introspect.h
 [Uninteresting stuff omitted...]
 
     #ifndef EXAMPLE_QMP_INTROSPECT_H
@@ -1321,7 +1321,7 @@ Example:
     extern const char example_qmp_schema_json[];
 
     #endif
-    $ cat qapi-generated/example-qmp-introspect.c
+    $ cat qapi-generated/example-qapi-introspect.c
 [Uninteresting stuff omitted...]
 
     const char example_qmp_schema_json[] = "["
diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
index 50385eff27..9dfc62bf5a 100644
--- a/docs/devel/writing-qmp-commands.txt
+++ b/docs/devel/writing-qmp-commands.txt
@@ -419,7 +419,7 @@ There are a number of things to be noticed:
    allocated by the implementation. This is so because the QAPI also generates
    a function to free its types and it cannot distinguish between dynamically
    or statically allocated strings
-6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
+6. You have to include "qapi/qapi-commands-misc.h" in qemu-timer.c
 
 Time to test the new command. Build qemu, run it as described in the "Testing"
 section and try this:
diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
index 430fe1b747..900d69d612 100644
--- a/docs/interop/qmp-intro.txt
+++ b/docs/interop/qmp-intro.txt
@@ -79,7 +79,7 @@ Escape character is '^]'.
 }
 
 Please refer to docs/interop/qemu-qmp-ref.* for a complete command
-reference, generated from qapi-schema.json.
+reference, generated from qapi/qapi-schema.json.
 
 QMP wiki page
 -------------
diff --git a/hmp.c b/hmp.c
index c86946866b..1f31de3217 100644
--- a/hmp.c
+++ b/hmp.c
@@ -28,7 +28,7 @@
 #include "monitor/qdev.h"
 #include "qapi/error.h"
 #include "qapi/opts-visitor.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 #include "qapi/qapi-commands-block.h"
 #include "qapi/qapi-commands-char.h"
 #include "qapi/qapi-commands-migration.h"
diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index a2964fbf25..012439a2e3 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -32,7 +32,7 @@
 #ifndef QOBJECT_H
 #define QOBJECT_H
 
-#include "qapi-builtin-types.h"
+#include "qapi/qapi-builtin-types.h"
 
 struct QObject {
     QType type;
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 9e57508446..5b2ed3f202 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -15,7 +15,7 @@
 #ifndef QAPI_VISITOR_H
 #define QAPI_VISITOR_H
 
-#include "qapi-builtin-types.h"
+#include "qapi/qapi-builtin-types.h"
 
 /*
  * The QAPI schema defines both a set of C data types, and a QMP wire
diff --git a/include/qom/object.h b/include/qom/object.h
index 5b5c016d8f..30db296af4 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -14,7 +14,7 @@
 #ifndef QEMU_OBJECT_H
 #define QEMU_OBJECT_H
 
-#include "qapi-builtin-types.h"
+#include "qapi/qapi-builtin-types.h"
 #include "qemu/queue.h"
 
 struct TypeImpl;
diff --git a/monitor.c b/monitor.c
index df670f3e15..d0e8d350fd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -69,14 +69,14 @@
 #include "exec/exec-all.h"
 #include "qemu/log.h"
 #include "qemu/option.h"
-#include "qmp-commands.h"
 #include "hmp.h"
 #include "qemu/thread.h"
 #include "block/qapi.h"
+#include "qapi/qapi-commands.h"
+#include "qapi/qapi-events.h"
 #include "qapi/error.h"
 #include "qapi/qmp-event.h"
-#include "qapi-event.h"
-#include "qmp-introspect.h"
+#include "qapi/qapi-introspect.h"
 #include "sysemu/qtest.h"
 #include "sysemu/cpus.h"
 #include "qemu/cutils.h"
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 7c487629f9..f7265c50a8 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -13,7 +13,7 @@
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "qemu/iov.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 #include "qapi/qmp/qerror.h"
 #include "qom/object.h"
 
diff --git a/qapi/misc.json b/qapi/misc.json
index 225631bf7d..506f2b9371 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -1618,7 +1618,7 @@
 #
 # Emitted when background dump has completed
 #
-# @result: DumpQueryResult type described in qapi-schema.json.
+# @result: final dump status
 #
 # @error: human-readable error string that provides
 #         hint on why dump failed. Only presents on failure. The
@@ -2833,7 +2833,7 @@
 #
 # Emitted when guest executes ACPI _OST method.
 #
-# @info: ACPIOSTInfo type as described in qapi-schema.json
+# @info: OSPM Status Indication
 #
 # Since: 2.1
 #
diff --git a/qapi-schema.json b/qapi/qapi-schema.json
similarity index 85%
rename from qapi-schema.json
rename to qapi/qapi-schema.json
index 689d06c530..25bce78352 100644
--- a/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -76,20 +76,20 @@
 # included sub-schemas inserted at the first include directive
 # (subsequent include directives have no effect).  To get a sane and
 # stable order, it's best to include each sub-schema just once, or
-# include it first in qapi-schema.json.
+# include it first right here.
 
-{ 'include': 'qapi/common.json' }
-{ 'include': 'qapi/sockets.json' }
-{ 'include': 'qapi/run-state.json' }
-{ 'include': 'qapi/crypto.json' }
-{ 'include': 'qapi/block.json' }
-{ 'include': 'qapi/char.json' }
-{ 'include': 'qapi/net.json' }
-{ 'include': 'qapi/rocker.json' }
-{ 'include': 'qapi/tpm.json' }
-{ 'include': 'qapi/ui.json' }
-{ 'include': 'qapi/migration.json' }
-{ 'include': 'qapi/transaction.json' }
-{ 'include': 'qapi/trace.json' }
-{ 'include': 'qapi/introspect.json' }
-{ 'include': 'qapi/misc.json' }
+{ 'include': 'common.json' }
+{ 'include': 'sockets.json' }
+{ 'include': 'run-state.json' }
+{ 'include': 'crypto.json' }
+{ 'include': 'block.json' }
+{ 'include': 'char.json' }
+{ 'include': 'net.json' }
+{ 'include': 'rocker.json' }
+{ 'include': 'tpm.json' }
+{ 'include': 'ui.json' }
+{ 'include': 'migration.json' }
+{ 'include': 'transaction.json' }
+{ 'include': 'trace.json' }
+{ 'include': 'introspect.json' }
+{ 'include': 'misc.json' }
diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 6151378ae4..ed08c5917c 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
 qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
 qga-obj-$(CONFIG_WIN32) += vss-win32.o
 qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
-qga-obj-y += qapi-generated/qga-qmp-commands.o
+qga-obj-y += qapi-generated/qga-qapi-commands.o
 
 qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 88807f3c78..417a50ce5f 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -17,7 +17,7 @@
 #include <sys/wait.h>
 #include <dirent.h>
 #include "qga/guest-agent-core.h"
-#include "qga-qmp-commands.h"
+#include "qga-qapi-commands.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index bedae32957..2d48394748 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -34,7 +34,7 @@
 
 #include "qga/guest-agent-core.h"
 #include "qga/vss-win32.h"
-#include "qga-qmp-commands.h"
+#include "qga-qapi-commands.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
diff --git a/qga/commands.c b/qga/commands.c
index 6d710dbb20..a64b34ccab 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -12,7 +12,7 @@
 
 #include "qemu/osdep.h"
 #include "qga/guest-agent-core.h"
-#include "qga-qmp-commands.h"
+#include "qga-qapi-commands.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/base64.h"
diff --git a/qga/main.c b/qga/main.c
index cb434d8c46..f9c83050c5 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -25,7 +25,7 @@
 #include "qapi/qmp/qstring.h"
 #include "qga/guest-agent-core.h"
 #include "qemu/module.h"
-#include "qga-qmp-commands.h"
+#include "qga-qapi-commands.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/error.h"
 #include "qga/channel.h"
diff --git a/qom/object.c b/qom/object.c
index 81b4f7ac48..f70a75c308 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -18,7 +18,7 @@
 #include "qapi/visitor.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/string-output-visitor.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 #include "qapi/qmp/qerror.h"
 #include "trace.h"
 
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 953449171b..21a7e0dbe6 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -232,13 +232,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
         self._regy = ''
         self._visited_ret_types = {}
 
-    # Temporary HACK:
-    def _module_basename(self, what, name):
-        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
-        if name == self._main_module:
-            return re.sub(r'qapi-commands', 'qmp-commands', basename)
-        return basename
-
     def _begin_module(self, name):
         self._visited_ret_types[self._genc] = set()
         commands = self._module_basename('qapi-commands', name)
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 5ad6708491..3dc523cf39 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -157,20 +157,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
         self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
         self._event_names = []
 
-    # Temporary HACK:
-    def _module_basename(self, what, name):
-        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
-        if name == self._main_module:
-            return re.sub(r'qapi-events', 'qapi-event', basename)
-        return basename
-
     def _begin_module(self, name):
         types = self._module_basename('qapi-types', name)
         visit = self._module_basename('qapi-visit', name)
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-#include "%(prefix)sqapi-event.h"
+#include "%(prefix)sqapi-events.h"
 #include "%(visit)s.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index f571cc134c..f66c397fb0 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -44,7 +44,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
 
     def __init__(self, prefix, unmask):
         QAPISchemaMonolithicCVisitor.__init__(
-            self, prefix, 'qmp-introspect',
+            self, prefix, 'qapi-introspect',
             ' * QAPI/QMP schema introspection', __doc__)
         self._unmask = unmask
         self._schema = None
@@ -53,7 +53,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
         self._name_map = {}
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
-#include "%(prefix)sqmp-introspect.h"
+#include "%(prefix)sqapi-introspect.h"
 
 ''',
                              prefix=prefix))
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 2a3c502cf6..64d9c0fb37 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -177,8 +177,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         self._genc.preamble_add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
-#include "qapi-builtin-types.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-types.h"
+#include "qapi/qapi-builtin-visit.h"
 '''))
         self._genh.preamble_add(mcgen('''
 #include "qapi/util.h"
@@ -195,7 +195,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
 ''',
                                       types=types, visit=visit))
         self._genh.preamble_add(mcgen('''
-#include "qapi-builtin-types.h"
+#include "qapi/qapi-builtin-types.h"
 '''))
 
     def visit_begin(self, schema):
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index de09966643..5d72d8936c 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -274,11 +274,11 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 '''))
         self._genh.preamble_add(mcgen('''
 #include "qapi/visitor.h"
-#include "qapi-builtin-types.h"
+#include "qapi/qapi-builtin-types.h"
 
 ''',
                                       prefix=prefix))
@@ -295,7 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
 ''',
                                       visit=visit, prefix=self._prefix))
         self._genh.preamble_add(mcgen('''
-#include "qapi-builtin-visit.h"
+#include "qapi/qapi-builtin-visit.h"
 #include "%(types)s.h"
 
 ''',
diff --git a/tests/.gitignore b/tests/.gitignore
index 2629cfc2f9..18e58b2183 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -60,7 +60,8 @@ test-keyval
 test-logging
 test-mul64
 test-opts-visitor
-test-qapi-event.[ch]
+test-qapi-commands.[ch]
+test-qapi-events.[ch]
 test-qapi-types.[ch]
 test-qapi-util
 test-qapi-visit.[ch]
@@ -71,11 +72,10 @@ test-qga
 test-qht
 test-qht-par
 test-qmp-cmds
-test-qmp-commands.[ch]
 test-qmp-event
 test-qobject-input-strict
 test-qobject-input-visitor
-test-qmp-introspect.[ch]
+test-qapi-introspect.[ch]
 test-qobject-output-visitor
 test-rcu-list
 test-replication
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 9a21ed7ee9..d71adf3996 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -566,8 +566,8 @@ qapi-schema += unknown-expr-key.json
 check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema))
 
 GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
-	tests/test-qmp-commands.h tests/test-qapi-event.h \
-	tests/test-qmp-introspect.h
+	tests/test-qapi-commands.h tests/test-qapi-events.h \
+	tests/test-qapi-introspect.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-qobject.o \
@@ -592,7 +592,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/tests
 test-util-obj-y = libqemuutil.a
 test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
 test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
-	tests/test-qapi-event.o tests/test-qmp-introspect.o \
+	tests/test-qapi-events.o tests/test-qapi-introspect.o \
 	$(test-qom-obj-y)
 benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
 test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
@@ -656,9 +656,9 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
 
 tests/test-qapi-types.c tests/test-qapi-types.h \
 tests/test-qapi-visit.c tests/test-qapi-visit.h \
-tests/test-qmp-commands.h tests/test-qmp-commands.c \
-tests/test-qapi-event.c tests/test-qapi-event.h \
-tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
+tests/test-qapi-commands.h tests/test-qapi-commands.c \
+tests/test-qapi-events.c tests/test-qapi-events.h \
+tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \
 tests/test-qapi-gen-timestamp ;
 tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
@@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
 tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
 tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
 tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
-tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
+tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o $(test-qapi-obj-y)
 tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
 tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
 
diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
index 24660d0868..5b1cee6912 100644
--- a/tests/test-qmp-cmds.c
+++ b/tests/test-qmp-cmds.c
@@ -3,12 +3,12 @@
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qstring.h"
-#include "test-qmp-commands.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "qapi/qobject-input-visitor.h"
 #include "tests/test-qapi-types.h"
 #include "tests/test-qapi-visit.h"
+#include "test-qapi-commands.h"
 
 static QmpCommandList qmp_commands;
 
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 5fbe7e551f..31f35b3e66 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -14,13 +14,13 @@
 #include "qemu/osdep.h"
 
 #include "qemu-common.h"
-#include "test-qapi-event.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qbool.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp-event.h"
+#include "test-qapi-events.h"
 
 typedef struct TestEventData {
     QDict *expect;
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index d3a56bd071..79b1a8cb17 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -24,8 +24,8 @@
 #include "qapi/qmp/qnum.h"
 #include "qapi/qmp/qstring.h"
 #include "qapi/qmp/qjson.h"
-#include "test-qmp-introspect.h"
-#include "qmp-introspect.h"
+#include "test-qapi-introspect.h"
+#include "qapi/qapi-introspect.h"
 
 typedef struct TestInputVisitorData {
     QObject *obj;
@@ -1376,7 +1376,7 @@ int main(int argc, char **argv)
                            NULL, test_visitor_in_fail_alternate);
     input_visitor_test_add("/visitor/input/fail/union-native-list",
                            NULL, test_visitor_in_fail_union_native_list);
-    input_visitor_test_add("/visitor/input/qmp-introspect",
+    input_visitor_test_add("/visitor/input/qapi-introspect",
                            NULL, test_visitor_in_qmp_introspect);
 
     g_test_run();
diff --git a/tpm.c b/tpm.c
index 2db03a09b2..ac580e6d47 100644
--- a/tpm.c
+++ b/tpm.c
@@ -182,7 +182,6 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
 
 /*
  * Walk the list of active TPM backends and collect information about them
- * following the schema description in qapi-schema.json.
  */
 TPMInfoList *qmp_query_tpm(Error **errp)
 {
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 51db47cd71..de6af6fbb9 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -32,7 +32,7 @@
 #include "ui/input.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
-#include "qmp-commands.h"
+#include "qapi/qapi-commands.h"
 #include "sysemu/blockdev.h"
 #include "qemu-version.h"
 #include <Carbon/Carbon.h>
diff --git a/ui/vnc.c b/ui/vnc.c
index d6329c8bd5..20cd9bb63d 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -35,10 +35,10 @@
 #include "qemu/timer.h"
 #include "qemu/acl.h"
 #include "qemu/config-file.h"
+#include "qapi/qapi-events.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-ui.h"
 #include "ui/input.h"
-#include "qapi-event.h"
 #include "crypto/hash.h"
 #include "crypto/tlscredsanon.h"
 #include "crypto/tlscredsx509.h"
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (26 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:47   ` Eric Blake
                     ` (2 more replies)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
                   ` (3 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

Fix up the reference to qmp-commands.hx in qmp.c.  Missed in commit
5032a16d1d.

Fix up the reference to qmp-commands.txt in
docs/xen-save-devices-state.txt.  Missed in commit 4d8bb958fa.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 docs/xen-save-devices-state.txt |  3 +--
 qmp.c                           | 14 +++++++-------
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt
index a72ecc8081..1912ecad25 100644
--- a/docs/xen-save-devices-state.txt
+++ b/docs/xen-save-devices-state.txt
@@ -8,8 +8,7 @@ These operations are normally used with migration (see migration.txt),
 however it is also possible to save the state of all devices to file,
 without saving the RAM or the block devices of the VM.
 
-This operation is called "xen-save-devices-state" (see
-qmp-commands.txt)
+The save operation is available as QMP command xen-save-devices-state.
 
 
 The binary format used in the file is the following:
diff --git a/qmp.c b/qmp.c
index a8d4eba973..ba82e1df9f 100644
--- a/qmp.c
+++ b/qmp.c
@@ -147,13 +147,13 @@ VncInfo2List *qmp_query_vnc_servers(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.
+ * qmp_unregister_commands_hack() ensures that QMP command query-spice
+ * exists only #ifdef CONFIG_SPICE.  Necessary for an accurate
+ * query-commands result.  However, the QAPI schema is blissfully
+ * unaware of that, and the QAPI code generator happily generates a
+ * dead qmp_marshal_query_spice() that calls qmp_query_spice().
+ * Provide it one, or else linking fails.  FIXME Educate the QAPI
+ * schema on CONFIG_SPICE.
  */
 SpiceInfo *qmp_query_spice(Error **errp)
 {
-- 
2.13.6

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

* [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (27 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
@ 2018-02-11  9:36 ` Markus Armbruster
  2018-02-12 22:48   ` Eric Blake
                     ` (2 more replies)
  2018-02-11 10:16 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code no-reply
                   ` (2 subsequent siblings)
  31 siblings, 3 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-11  9:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, marcandre.lureau, eblake

We used to generate first test and later QGA QAPI code into
qapi-generated/.  Commit b93b63f574 moved the test code to tests/.
Commit 54c2e50205 moved the QGA code to qga/qapi-generated/.  The
directory has been unused since.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 .gitignore | 1 -
 Makefile   | 1 -
 configure  | 1 -
 3 files changed, 3 deletions(-)

diff --git a/.gitignore b/.gitignore
index dabfe6bea8..4055e12ee8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,7 +27,6 @@
 /libuser
 /linux-headers/asm
 /qga/qapi-generated
-/qapi-generated
 /qapi-gen-timestamp
 /qapi/qapi-builtin-types.[ch]
 /qapi/qapi-builtin-visit.[ch]
diff --git a/Makefile b/Makefile
index 84411ee6ab..7eb1ede6f4 100644
--- a/Makefile
+++ b/Makefile
@@ -726,7 +726,6 @@ clean:
 	rm -f trace/generated-tracers-dtrace.h*
 	rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
 	rm -f qapi-gen-timestamp
-	rm -rf qapi-generated
 	rm -rf qga/qapi-generated
 	for d in $(ALL_SUBDIRS); do \
 	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
diff --git a/configure b/configure
index 62562f08cf..f564a1639e 100755
--- a/configure
+++ b/configure
@@ -7015,7 +7015,6 @@ DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-sche
 DIRS="$DIRS docs docs/interop fsdev scsi"
 DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
 DIRS="$DIRS roms/seabios roms/vgabios"
-DIRS="$DIRS qapi-generated"
 FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
 FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
 FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
-- 
2.13.6

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

* Re: [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (28 preceding siblings ...)
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
@ 2018-02-11 10:16 ` no-reply
  2018-02-26 22:57 ` [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file Eric Blake
  2018-02-27 14:19 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Eric Blake
  31 siblings, 0 replies; 110+ messages in thread
From: no-reply @ 2018-02-11 10:16 UTC (permalink / raw)
  To: armbru; +Cc: famz, qemu-devel, marcandre.lureau, mdroth

Hi,

This series failed docker-mingw@fedora 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: 20180211093607.27351-1-armbru@redhat.com
Subject: [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI 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-mingw@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
88c36fed50 qapi: Don't create useless directory qapi-generated
8695c58a23 Fix up dangling references to qmp-commands.* in comment and doc
cb0173d2de qapi: Move qapi-schema.json to qapi/, rename generated files
0163832937 docs: Correct outdated information on QAPI
0e8593c3cc docs/devel/writing-qmp-commands: Update for modular QAPI
610c107fba qapi: Empty out qapi-schema.json
978b56117d Include less of the generated modular QAPI headers
b9fbec1f14 qapi: Generate separate .h, .c for each module
349f60fd78 qapi/common: Fix guardname() for funny filenames
7d0c330c11 qapi/types qapi/visit: Generate built-in stuff into separate files
6be749acd0 qapi: Make code-generating visitors use QAPIGen more
26fb1118b1 qapi: Rename generated qmp-marshal.c to qmp-commands.c
3373ff0b73 qapi: Record 'include' directives in intermediate representation
992e298bed qapi: Generate in source order
27ec87b85b qapi: Record 'include' directives in parse tree
704eb94f85 qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
679e456092 qapi: Lift error reporting from QAPISchema.__init__() to callers
b6747d37d3 qapi/common: Eliminate QAPISchema.exprs
12c8bc8c3c qapi: Improve include file name reporting in error messages
15d87d797d qapi: Touch generated files only when they change
c1fb7b93d8 qapi-gen: Convert from getopt to argparse
8174e1f7f9 qapi-gen: New common driver for code and doc generators
76b229359e qapi: Turn generators into modules
e9687814c8 qapi: Reduce use of global variables in generators some
df03d3d345 qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
8dcb95864b qapi: Rename variable holding the QAPISchemaGenFOOVisitor
176807c729 qapi: Generate up-to-date copyright notice
57f04f7bcd qapi: Streamline boilerplate comment generation
dc8f4505cb Include qapi/qmp/qerror.h exactly where needed

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   fedora
  GEN     /var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar
Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot'...
done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb'
Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce'
  COPY    RUNNER
    RUN test-mingw in qemu:fedora 
Packages installed:
PyYAML-3.12-5.fc27.x86_64
SDL-devel-1.2.15-29.fc27.x86_64
bc-1.07.1-3.fc27.x86_64
bison-3.0.4-8.fc27.x86_64
bzip2-1.0.6-24.fc27.x86_64
ccache-3.3.5-1.fc27.x86_64
clang-5.0.1-1.fc27.x86_64
findutils-4.6.0-14.fc27.x86_64
flex-2.6.1-5.fc27.x86_64
gcc-7.3.1-2.fc27.x86_64
gcc-c++-7.3.1-2.fc27.x86_64
gettext-0.19.8.1-12.fc27.x86_64
git-2.14.3-2.fc27.x86_64
glib2-devel-2.54.3-2.fc27.x86_64
hostname-3.18-4.fc27.x86_64
libaio-devel-0.3.110-9.fc27.x86_64
libasan-7.3.1-2.fc27.x86_64
libfdt-devel-1.4.6-1.fc27.x86_64
libubsan-7.3.1-2.fc27.x86_64
make-4.2.1-4.fc27.x86_64
mingw32-SDL-1.2.15-9.fc27.noarch
mingw32-bzip2-1.0.6-9.fc27.noarch
mingw32-curl-7.54.1-2.fc27.noarch
mingw32-glib2-2.54.1-1.fc27.noarch
mingw32-gmp-6.1.2-2.fc27.noarch
mingw32-gnutls-3.5.13-2.fc27.noarch
mingw32-gtk2-2.24.31-4.fc27.noarch
mingw32-gtk3-3.22.16-1.fc27.noarch
mingw32-libjpeg-turbo-1.5.1-3.fc27.noarch
mingw32-libpng-1.6.29-2.fc27.noarch
mingw32-libssh2-1.8.0-3.fc27.noarch
mingw32-libtasn1-4.13-1.fc27.noarch
mingw32-nettle-3.3-3.fc27.noarch
mingw32-pixman-0.34.0-3.fc27.noarch
mingw32-pkg-config-0.28-9.fc27.x86_64
mingw64-SDL-1.2.15-9.fc27.noarch
mingw64-bzip2-1.0.6-9.fc27.noarch
mingw64-curl-7.54.1-2.fc27.noarch
mingw64-glib2-2.54.1-1.fc27.noarch
mingw64-gmp-6.1.2-2.fc27.noarch
mingw64-gnutls-3.5.13-2.fc27.noarch
mingw64-gtk2-2.24.31-4.fc27.noarch
mingw64-gtk3-3.22.16-1.fc27.noarch
mingw64-libjpeg-turbo-1.5.1-3.fc27.noarch
mingw64-libpng-1.6.29-2.fc27.noarch
mingw64-libssh2-1.8.0-3.fc27.noarch
mingw64-libtasn1-4.13-1.fc27.noarch
mingw64-nettle-3.3-3.fc27.noarch
mingw64-pixman-0.34.0-3.fc27.noarch
mingw64-pkg-config-0.28-9.fc27.x86_64
nettle-devel-3.4-1.fc27.x86_64
perl-5.26.1-402.fc27.x86_64
pixman-devel-0.34.0-4.fc27.x86_64
python3-3.6.2-13.fc27.x86_64
sparse-0.5.1-2.fc27.x86_64
tar-1.29-7.fc27.x86_64
which-2.21-4.fc27.x86_64
zlib-devel-1.2.11-4.fc27.x86_64

Environment variables:
TARGET_LIST=
PACKAGES=ccache gettext git tar PyYAML sparse flex bison python3 bzip2 hostname     glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel     gcc gcc-c++ clang make perl which bc findutils libaio-devel     nettle-devel libasan libubsan     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
J=8
V=
HOSTNAME=8e24a3c7cddb
DEBUG=
SHOW_ENV=1
PWD=/
HOME=/root
CCACHE_DIR=/var/tmp/ccache
DISTTAG=f27container
QEMU_CONFIGURE_OPTS=--python=/usr/bin/python3
FGC=f27
TEST_DIR=/tmp/qemu-test
SHLVL=1
FEATURES=mingw clang pyyaml asan dtc
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAKEFLAGS= -j8
EXTRA_CONFIGURE_OPTS=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install --python=/usr/bin/python3 --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=1.2 --with-gtkabi=2.0
Install prefix    /tmp/qemu-test/install
BIOS directory    /tmp/qemu-test/install
firmware path     /tmp/qemu-test/install/share/qemu-firmware
binary directory  /tmp/qemu-test/install
library directory /tmp/qemu-test/install/lib
module directory  /tmp/qemu-test/install/lib
libexec directory /tmp/qemu-test/install/libexec
include directory /tmp/qemu-test/install/include
config directory  /tmp/qemu-test/install
local state directory   queried at runtime
Windows SDK       no
Source path       /tmp/qemu-test/src
GIT binary        git
GIT submodules    
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            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1  -I$(SRC_PATH)/dtc/libfdt -Werror -DHAS_LIBSSH2_SFTP_FSYNC -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  -Wexpansion-to-defined -Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/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            /usr/bin/python3 -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (1.2.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
Multipath 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
HVF support       no
WHPX support      no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support 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
TPM emulator      no
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     yes
NUMA host support no
libxml2           no
tcmalloc support  no
jemalloc support  no
avx2 optimization yes
replication support yes
VxHS block device no
capstone          no

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

WARNING: Use of SDL 1.2 is deprecated and will be removed in
WARNING: future releases. Please switch to using SDL 2.0
  GEN     config-host.h
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     aarch64-softmmu/config-devices.mak.tmp
  GEN     qemu-options.def
  GEN     qapi-gen
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     trace/generated-helpers.c
  GEN     aarch64-softmmu/config-devices.mak
  GEN     module_block.h
  GEN     ui/input-keymap-atset1-to-qcode.c
  GEN     ui/input-keymap-linux-to-qcode.c
  GEN     ui/input-keymap-qcode-to-atset1.c
  GEN     ui/input-keymap-qcode-to-atset2.c
  GEN     ui/input-keymap-qcode-to-atset3.c
Traceback (most recent call last):
  File "/tmp/qemu-test/src/scripts/qapi-gen.py", line 11, in <module>
    from qapi.common import QAPIError, QAPISchema
  File "/tmp/qemu-test/src/scripts/qapi/common.py", line 2002
    fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0666)
                                                      ^
SyntaxError: invalid token
  GEN     ui/input-keymap-qcode-to-linux.c
make: *** [Makefile:665: qapi-gen-timestamp] Error 1
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 407, in <module>
    sys.exit(main())
  File "./tests/docker/docker.py", line 404, in main
    return args.cmdobj.run(args, argv)
  File "./tests/docker/docker.py", line 261, in run
    return Docker().run(argv, args.keep, quiet=args.quiet)
  File "./tests/docker/docker.py", line 229, in run
    quiet=quiet)
  File "./tests/docker/docker.py", line 147, in _do_check
    return subprocess.check_call(self._command + cmd, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 186, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['docker', 'run', '--label', 'com.qemu.instance.uuid=7c5f6f3e0f1411e8af5c52540069c830', '-u', '0', '--security-opt', 'seccomp=unconfined', '--rm', '--net=none', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=8', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/root/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2
make[1]: *** [tests/docker/Makefile.include:129: docker-run] Error 1
make: *** [tests/docker/Makefile.include:163: docker-run-test-mingw@fedora] Error 2

real	1m0.694s
user	0m4.526s
sys	0m3.165s
=== 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] 110+ messages in thread

* Re: [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
@ 2018-02-12 16:55   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 16:55 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   block.c                 | 1 -
>   block/qcow2.c           | 1 -
>   chardev/char-fe.c       | 1 +
>   chardev/char.c          | 1 +
>   qom/object_interfaces.c | 1 +
>   scripts/qapi-visit.py   | 2 +-
>   6 files changed, 4 insertions(+), 3 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

(May get stale again soon; we'll have fun with last-minute rebasing at 
the time this is ready for a pull request)

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

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

* Re: [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
@ 2018-02-12 16:59   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
  2018-02-16 22:56   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 16:59 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Rename the variable holding the QAPISchemaGenFOOVisitor from gen to
> vis, to avoid confusion in the next commit.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   scripts/qapi-commands.py   | 8 ++++----
>   scripts/qapi-event.py      | 8 ++++----
>   scripts/qapi-introspect.py | 8 ++++----
>   scripts/qapi-types.py      | 8 ++++----
>   scripts/qapi-visit.py      | 8 ++++----
>   5 files changed, 20 insertions(+), 20 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
@ 2018-02-12 19:40   ` Eric Blake
  2018-02-16 22:53   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:40 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Each generator carries a copyright notice for the generator itself,
> and another one for the files it generates.  Only the former have been
> updated along the way, the latter have not, and are all out of date.
> 
> Fix by copying the generator's copyright notice to the generated files
> instead.  Note that the fix doesn't copy the "Authors:" part; the
> generated files' outdated Authors list goes away without replacement.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---

> +++ b/scripts/qapi-commands.py

> @@ -257,16 +258,11 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>   
>   blurb = '''
>    * Schema-defined QAPI/QMP commands
> - *
> - * Copyright IBM, Corp. 2011
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
>   '''

This is where we could shorten blurb to a one-line assignment instead of 
a multiline '''...''' string, if desired.  R-b stands either way, though.

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

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

* Re: [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
@ 2018-02-12 19:42   ` Eric Blake
  2018-02-23 17:20     ` Markus Armbruster
  2018-02-18 22:16   ` Michael Roth
  1 sibling, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:42 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Whenever qapi-schema.json changes, we run six programs eleven times to
> update eleven files.  Similar for qga/qapi-schema.json.  This is
> silly.  Replace the six programs by a single program that spits out
> all eleven files.
> 
> The programs become modules in new Python package qapi, along with the
> helper library.  This requires moving them to scripts/qapi/.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   .gitignore                                         |  2 +
>   Makefile                                           | 86 +++++++++----------
>   docs/devel/qapi-code-gen.txt                       | 97 ++++++++++------------
>   monitor.c                                          |  2 +-
>   qapi-schema.json                                   |  2 +-
>   scripts/qapi-gen.py                                | 41 +++++++++
>   scripts/qapi/__init__.py                           |  0
>   scripts/{qapi-commands.py => qapi/commands.py}     | 23 ++---
>   scripts/{qapi.py => qapi/common.py}                | 18 +---
>   scripts/{qapi2texi.py => qapi/doc.py}              | 29 ++-----
>   scripts/{qapi-event.py => qapi/events.py}          | 23 ++---
>   scripts/{qapi-introspect.py => qapi/introspect.py} | 32 ++-----
>   scripts/{qapi-types.py => qapi/types.py}           | 34 ++------
>   scripts/{qapi-visit.py => qapi/visit.py}           | 34 ++------
>   tests/Makefile.include                             | 56 ++++++-------
>   tests/qapi-schema/test-qapi.py                     |  4 +-
>   16 files changed, 193 insertions(+), 290 deletions(-)
>   create mode 100755 scripts/qapi-gen.py
>   create mode 100644 scripts/qapi/__init__.py
>   rename scripts/{qapi-commands.py => qapi/commands.py} (94%)
>   rename scripts/{qapi.py => qapi/common.py} (99%)
>   rename scripts/{qapi2texi.py => qapi/doc.py} (92%)
>   mode change 100755 => 100644

Still forgot mention that the mode bit change was intentional, but not 
worth a respin for just that.

>   rename scripts/{qapi-event.py => qapi/events.py} (92%)
>   rename scripts/{qapi-introspect.py => qapi/introspect.py} (90%)
>   rename scripts/{qapi-types.py => qapi/types.py} (90%)
>   rename scripts/{qapi-visit.py => qapi/visit.py} (92%)

Reviewed-by: Eric Blake <eblake@redhat.com>

> +++ b/docs/devel/qapi-code-gen.txt

> -    $ python scripts/qapi-event.py --output-dir="qapi-generated"
> -    --prefix="example-" example-schema.json
>       $ cat qapi-generated/example-qapi-event.h
>   [Uninteresting stuff omitted...]
>   
> @@ -1302,23 +1296,22 @@ Example:
>       }
>   
>       const char *const example_QAPIEvent_lookup[] = {
> -        [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
> +
> +[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>           [EXAMPLE_QAPI_EVENT__MAX] = NULL,
>       };

Looks like our generated code indentation has slightly regressed from 
what we would write by hand, but it's still okay for generated code (and 
the commit message in 5/29 did call that out)

> +++ b/scripts/qapi-gen.py

> +++ b/scripts/qapi/commands.py
> @@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>   See the COPYING file in the top-level directory.
>   """
>   
> -from qapi import *
> +from qapi.common import *
>   
>   
>   def gen_command_decl(name, arg_type, boxed, ret_type):
> @@ -255,13 +255,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>           self._regy += gen_register_command(name, success_response)
>   
>   
> -def main(argv):
> -    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> -
> -    blurb = '''
> - * Schema-defined QAPI/QMP commands
> -'''
> -
> +def gen_commands(schema, output_dir, prefix):
> +    blurb = ' * Schema-defined QAPI/QMP commands'

We discussed whether to make the assignment to blurb be a one-liner in 
an earlier patch, but I'm also fine with the churn you have over the 
course of the series.


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

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

* Re: [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
@ 2018-02-12 19:44   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
  2018-02-18 22:31   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:44 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> argparse is nicer to use than getopt, and gives us --help almost for
> free.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   scripts/qapi-gen.py    | 48 ++++++++++++++++++++++++++++++------------------
>   scripts/qapi/common.py | 43 -------------------------------------------
>   2 files changed, 30 insertions(+), 61 deletions(-)
> 

More functionality in fewer lines of code - always a win ;)

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
@ 2018-02-12 19:48   ` Eric Blake
  2018-02-13 15:22     ` Marc-Andre Lureau
  2018-02-18 22:43   ` Michael Roth
  1 sibling, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:48 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> A massive number of objects depends on QAPI-generated headers.  In my
> "build everything" tree, it's roughly 4800 out of 5100.  This is
> particularly annoying when only some of the generated files change,
> say for a doc fix.
> 
> Improve qapi-gen.py to touch its output files only if they actually
> change.  Rebuild time for a QAPI doc fix drops from many minutes to a
> few seconds.  Rebuilds get faster for certain code changes, too.  For
> instance, adding a simple QMP event now recompiles less than 200
> instead of 4800 objects.  But adding a QAPI type is as bad as ever;
> we've clearly got more work to do.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
>   scripts/qapi/common.py | 11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 8290795dc1..2e58573a39 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1951,9 +1951,16 @@ class QAPIGen(object):
>               except os.error as e:
>                   if e.errno != errno.EEXIST:
>                       raise
> -        f = open(os.path.join(output_dir, fname), 'w')
> -        f.write(self._top(fname) + self._preamble + self._body
> +        fd = os.open(os.path.join(output_dir, fname),
> +                     os.O_RDWR | os.O_CREAT, 0666)

patchew complained here for mingw; I'm not sure why.

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

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

* Re: [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
@ 2018-02-12 19:52   ` Eric Blake
  2018-02-18 23:17   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:52 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   scripts/qapi-gen.py            |  8 ++++++--
>   scripts/qapi/common.py         | 23 +++++++++--------------
>   tests/qapi-schema/test-qapi.py | 10 ++++++++--
>   3 files changed, 23 insertions(+), 18 deletions(-)

The commit message didn't say why, but the change is reasonable.

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
@ 2018-02-12 19:56   ` Eric Blake
  2018-02-18 23:32   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 19:56 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   scripts/qapi/common.py | 15 +++++++++------
>   1 file changed, 9 insertions(+), 6 deletions(-)

Again, not much mention of 'why' in the commit message.  But 
centralizing the initialization operations in one place rather than 
having to chase down multiple places is good.

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
@ 2018-02-12 20:03   ` Eric Blake
  2018-02-18 23:57   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 20:03 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> The parse tree is a list of expressions.  Except include expressions
> currently get replaced by the included file's parse tree.
> 
> Instead of throwing away the include expression, keep it with the file
> name expanded so you don't have to track the including file's
> directory to make sense of it.
> 
> A future commit will put this include expression to use.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   scripts/qapi/common.py | 21 +++++++++++++++++----
>   1 file changed, 17 insertions(+), 4 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
@ 2018-02-12 20:06   ` Eric Blake
  2018-02-19  0:01   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 20:06 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> The generators' conversion to visitors (merge commit 9e72681d16)
> changed the processing order of entities from source order to
> alphabetical order.  The next commit needs source order, so change it
> back.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation Markus Armbruster
@ 2018-02-12 20:34   ` Eric Blake
  2018-02-23 17:33     ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 20:34 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> The include directive permits modular QAPI schemata, but the generated
> code is monolithic all the same.  To permit generating modular code,
> the front end needs to pass more information on inclusions to the back
> ends.  The commit before last added the necessary information to the
> parse tree.  This commit adds it to the intermediate representation
> and its QAPISchemaVisitor.  A later commit will use this to to
> generate modular code.
> 
> New entity QAPISchemaInclude represents inclusions.  Call new visitor
> method visit_include() for it, so visitors can see the sub-modules a
> module includes.
> 
> Note that unlike other entities, QAPISchemaInclude has no name, and is
> therefore not added to entity_dict.
> 
> New QAPISchemaEntity attribute @module names the entity's source file.
> Call new visitor method visit_module() when it changes during a visit,
> so visitors can keep track of the module being visited.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> @@ -1479,16 +1497,19 @@ class QAPISchema(object):
>           self._entity_dict = {}
>           self._predefining = True
>           self._def_predefineds()
> -        self._predefining = False
>           self._def_exprs(exprs)
>           self.check()

Why does self._predfining not need to be toggled anymore?  Do we even 
need this variable any more...

> 
>      def _def_entity(self, ent):
>          # Only the predefined types are allowed to not have info
>          assert ent.info or self._predefining
> -        assert ent.name not in self._entity_dict

...and/or is this assert now worthless?


> +++ b/tests/qapi-schema/comments.out
> @@ -1,4 +1,5 @@
>   object q_empty
>   enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>       prefix QTYPE
> +module comments.json
>   enum Status ['good', 'bad', 'ugly']

Based on the generated output, it looks like you can tell whether you 
are in the predefining stage by not having any module at all; the first 
visit_module call is what flips the switch that everything else is 
defined by a module and must therefore have associated info.

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

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

* Re: [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
@ 2018-02-12 20:56   ` Eric Blake
  2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19  0:21   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 20:56 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> All generated .c are named like their .h, except for qmp-marshal.c and
> qmp-commands.h.  To add to the confusion, tests-qmp-commands.c falsely
> matches generated test-qmp-commands.h.
> 
> Get rid of this unnecessary complication.

Yay for saner naming.

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   .gitignore                                     |  3 +--
>   Makefile                                       |  6 +++---
>   Makefile.objs                                  |  2 +-
>   docs/devel/qapi-code-gen.txt                   |  6 +++---
>   qga/Makefile.objs                              |  2 +-
>   scripts/qapi/commands.py                       |  2 +-
>   tests/.gitignore                               |  5 ++---
>   tests/Makefile.include                         | 10 +++++-----
>   tests/{test-qmp-commands.c => test-qmp-cmds.c} |  0
>   9 files changed, 17 insertions(+), 19 deletions(-)
>   rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (100%)
> 

> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-cmds.c
> similarity index 100%
> rename from tests/test-qmp-commands.c
> rename to tests/test-qmp-cmds.c
> 

Noticed while renaming this file - it's non-trivial in length, but bears 
no copyright or license clause.  Perhaps we should add that (but can be 
separate patch).

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
@ 2018-02-12 21:06   ` Eric Blake
  2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19 15:52   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 21:06 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> The use of QAPIGen is rather shallow so far: most of the output
> accumulation is not converted.  Take the next step: convert output
> accumulation in the code-generating visitor classes.  Helper functions
> outside these classes are not converted.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   scripts/qapi/commands.py   | 71 ++++++++++++++++------------------------
>   scripts/qapi/common.py     | 13 ++++++++
>   scripts/qapi/doc.py        | 74 ++++++++++++++++++++----------------------
>   scripts/qapi/events.py     | 55 ++++++++++++-------------------
>   scripts/qapi/introspect.py | 56 +++++++++++++-------------------
>   scripts/qapi/types.py      | 81 +++++++++++++++++++---------------------------
>   scripts/qapi/visit.py      | 80 +++++++++++++++++++--------------------------
>   7 files changed, 188 insertions(+), 242 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
@ 2018-02-12 21:44   ` Eric Blake
  2018-02-23 17:36     ` Markus Armbruster
  2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19 19:30   ` Michael Roth
  2 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 21:44 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Linking code from multiple separate QAPI schemata into the same
> program is possible, but involves some weirdness around built-in
> types:
> 
> * We generate code for built-in types into .c only with option
>    --builtins.  The user is responsible for generating code for exactly
>    one QAPI schema per program with --builtins.
> 
> * We generate code for built-in types into .h regardless of
>    --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN.  Because all
>    copies of this code are exactly the same, including any combination
>    of these headers works.
> 
> Replace this contraption by something more conventional: generate code
> for built-in types into their very own files: qapi-builtin-types.c,
> qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
> only with --builtins.  Obey --output-dir, but ignore --prefix for
> them.
> 
> Make qapi-types.h include qapi-builtin-types.h.  With multiple
> schemata you now have multiple qapi-types.[ch], but only one
> qapi-builtin-types.[ch].  Same for qapi-visit.[ch] and
> qapi-builtin-visit.[ch].
> 
> Bonus: if all you need is built-in stuff, you can include a much
> smaller header.  To be exploited shortly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
> @@ -2046,6 +2046,7 @@ class QAPIGenH(QAPIGenC):
>   
>   
>   class QAPIGenDoc(QAPIGen):
> +
>       def _top(self, fname):
>           return (QAPIGen._top(self, fname)
>                   + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')

Does this hunk belong in an earlier patch?

Otherwise,
Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module Markus Armbruster
@ 2018-02-12 22:06   ` Eric Blake
  2018-02-23 17:41     ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:06 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> Our qapi-schema.json is composed of modules connected by include
> directives, but the generated code is monolithic all the same: one
> qapi-types.h with all the types, one qapi-visit.h with all the
> visitors, and so forth.  These monolithic headers get included all
> over the place.  In my "build everything" tree, adding a QAPI type
> recompiles about 4800 out of 5100 objects.
> 
> We wouldn't write such monolithic headers by hand.  It stands to
> reason that we shouldn't generate them, either.
> 
> Split up generated qapi-types.h to mirror the schema's modular
> structure: one header per module.  Name the main module's header
> qapi-types.h, and sub-module D/B.json's header D/qapi-types-B.h.
> 
> Mirror the schema's includes in the headers, so that qapi-types.h gets
> you everything exactly as before.  If you need less, you can include
> one or more of the sub-module headers.  To be exploited shortly.
> 
> Split up qapi-types.c, qapi-visit.h, qapi-visit.c, qmp-commands.h,
> qmp-commands.c, qapi-event.h, qapi-event.c the same way.
> qmp-introspect.h, qmp-introspect.c and qapi.texi remain monolithic.

Make sense.

> 
> The split of qmp-commands.c duplicates static helper function
> qmp_marshal_output_str() in qapi-commands-char.c and
> qapi-commands-misc.c.  This happens when commands returning the same
> type occur in multiple modules.  Not worth avoiding.

As long as it is static, and neither .c file includes the other, we're 
fine (gdb may have a harder time figuring out which copy to put a 
breakpoint on, but that's not too terrible).

> 
> Since I'm going to rename qapi-event.[ch] to qapi-events.[ch], and
> qmp-commands.[ch] to qapi-commands.[ch], name the shards that way
> already, to reduce churn.  This requires temporary hacks in
> commands.py and events.py.  They'll go away with the rename.

The planned rename makes sense; prepping now is fine.

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   .gitignore               |  60 ++++++++++++++++++++++++
>   Makefile                 | 120 +++++++++++++++++++++++++++++++++++++++++++++++
>   Makefile.objs            |  65 ++++++++++++++++++++++++-
>   scripts/qapi/commands.py |  35 +++++++++-----
>   scripts/qapi/common.py   |  21 +++++++--
>   scripts/qapi/events.py   |  19 ++++++--
>   6 files changed, 300 insertions(+), 20 deletions(-)
> 
> diff --git a/.gitignore b/.gitignore
> index 9477a08b6b..42c57998fd 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -31,7 +31,67 @@
>   /qapi-gen-timestamp
>   /qapi-builtin-types.[ch]
>   /qapi-builtin-visit.[ch]
> +/qapi/qapi-commands-block-core.[ch]
> +/qapi/qapi-commands-block.[ch]

Is it worth using a glob instead of specific patterns, as in:

/qapi/qapi-commands-*.[ch]

Maybe being precise doesn't hurt, if we aren't adding sub-modules all 
that often; but being generous with a glob makes it less likely that a 
future module addition will forget to update .gitignore.


> +++ b/Makefile
> @@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak
>   GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
>   GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
>   GENERATED_FILES += qapi-types.h qapi-types.c
> +GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c

For the makefile, I'd suggest using an intermediate list of module 
names, and then using make string operations to expand it into larger 
lists, to cut down on the repetition.  Something like (untested):

QAPI_MODULES = block-core block char common ...
GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix 
.c,$(QAPI_MODULES))
GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix 
.h,$(QAPI_MODULES))


> @@ -525,10 +585,70 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>   
>   qapi-builtin-types.c qapi-builtin-types.h \
>   qapi-types.c qapi-types.h \
> +qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
> +qapi/qapi-types-block.c qapi/qapi-types-block.h \

And repeating the list of filenames; again, an intermediate variable 
would let you do:

QAPI_GENERATED_FILES = ...
GENERATED_FILES += $(QAPI_GENERATED_FILES)

$(QAPI_GENERATED_FILES): ...

>   qmp-introspect.h qmp-introspect.c \
>   qapi-doc.texi: \
>   qapi-gen-timestamp ;

Not only does it cut down on the repetition, but it will make adding a 
future module easier.

> diff --git a/Makefile.objs b/Makefile.objs
> index 2813e984fd..7a55d45669 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -3,8 +3,56 @@
>   stub-obj-y = stubs/ crypto/
>   util-obj-y = util/ qobject/ qapi/
>   util-obj-y += qapi-builtin-types.o
> +util-obj-y += qapi-types.o
> +util-obj-y += qapi/qapi-types-block-core.o

Perhaps this can also exploit make text manipulation?

Otherwise looks good.

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

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

* Re: [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
@ 2018-02-12 22:13   ` Eric Blake
  2018-02-23 17:47     ` Markus Armbruster
  2018-02-13 15:54   ` Marc-Andre Lureau
  1 sibling, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:13 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> In my "build everything" tree, a change to the types in
> qapi-schema.json triggers a recompile of about 4800 out of 5100
> objects.
> 
> The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h,
> qapi-types.h.  Each of these headers still includes all its shards.
> Reduce compile time by including just the shards we actually need.
> 
> To illustrate the benefits: adding a type to qapi/migration.json now
> recompiles some 2300 instead of 4800 objects.  The next commit will
> improve it further.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   backends/cryptodev.c             |  1 -
>   backends/hostmem.c               |  3 ++-

How did you determine which shards to include where? Remove all shards, 
try compiling, and see what fails, then add back in the right includes? 
Or was it scripted somehow?  (Trying to figure out, in case I have to 
rebase this patch)

> +++ b/block/crypto.c
> @@ -24,9 +24,9 @@
>   #include "sysemu/block-backend.h"
>   #include "crypto/block.h"
>   #include "qapi/opts-visitor.h"
> +#include "qapi/qapi-visit-crypto.h"
>   #include "qapi/qmp/qdict.h"
>   #include "qapi/qobject-input-visitor.h"
> -#include "qapi-visit.h"
>   #include "qapi/error.h"

Any rhyme or reason to the resulting include order that I should be 
looking for (we aren't alphabetical in general, but if your changes were 
trying to honor a particular pattern among the few affected lines, 
that's useful to know).

> +++ b/scripts/qapi/commands.py

The non-mechanical portion of the patch :)

> @@ -241,6 +241,9 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>   
>       def _begin_module(self, name):
>           self._visited_ret_types[self._genc] = set()
> +        commands = self._module_basename('qapi-commands', name)
> +        types = self._module_basename('qapi-types', name)
> +        visit = self._module_basename('qapi-visit', name)
>           self._genc.add(mcgen('''
>   #include "qemu/osdep.h"
>   #include "qemu-common.h"
> @@ -251,18 +254,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>   #include "qapi/qobject-input-visitor.h"
>   #include "qapi/dealloc-visitor.h"
>   #include "qapi/error.h"
> -#include "%(prefix)sqapi-types.h"
> -#include "%(prefix)sqapi-visit.h"
> -#include "%(prefix)sqmp-commands.h"
> +#include "%(visit)s.h"
> +#include "%(commands)s.h"
>   
>   ''',
> -                             prefix=self._prefix))
> +                             commands=commands, visit=visit))
>           self._genh.add(mcgen('''
> -#include "%(prefix)sqapi-types.h"
> +#include "%(types)s.h"
>   #include "qapi/qmp/dispatch.h"
>   
>   ''',
> -                             prefix=self._prefix))
> +                             types=types))

Makes sense.

The compiler will catch anything we did wrong.

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json Markus Armbruster
@ 2018-02-12 22:26   ` Eric Blake
  2018-02-23 17:50     ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:26 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> The previous commit improved compile time by including less of the
> generated QAPI headers.  This is impossible for stuff defined directly
> in qapi-schema.json, because that ends up in headers that that pull in
> everything.
> 
> Move everything but include directives from qapi-schema.json to new
> sub-module qapi/misc.json, then include just the "misc" shard where
> possible.
> 
> It's not possible everywhere, except:

Odd wording, did you mean one of:

It's possible everywhere, except:
It's almost possible everywhere, except:

> 
> * monitor.c needs qmp-command.h to get qmp_init_marshall()

s/marshall/marshal/

> 
> * monitor.c, ui/vnc.c and the generated qapi-event-FOO.c need
>    qapi-event.h to get enum QAPIEvent
> 
> Perhaps we'll get rid of those some other day.
> 
> Adding a type to qapi/migration.json now recompiles some 120 instead
> of 2300 out of 5100 objects.

Getting better :)

> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   .gitignore                         |    4 +
>   Makefile                           |    9 +
>   Makefile.objs                      |    4 +
>   arch_init.c                        |    2 +-
>   balloon.c                          |    2 +-
>   block/iscsi.c                      |    2 +-
>   cpus.c                             |    2 +-
>   dump.c                             |    4 +-
>   hmp.c                              |   10 +-
>   hw/acpi/core.c                     |    2 +-
>   hw/acpi/cpu.c                      |    2 +-
>   hw/acpi/memory_hotplug.c           |    2 +-
>   hw/acpi/vmgenid.c                  |    2 +-
>   hw/core/qdev.c                     |    2 +-
>   hw/i386/xen/xen-hvm.c              |    2 +-
>   hw/ipmi/ipmi.c                     |    2 +-
>   hw/pci/pci-stub.c                  |    2 +-
>   hw/pci/pci.c                       |    2 +-
>   hw/ppc/spapr_rtc.c                 |    2 +-
>   hw/s390x/s390-skeys.c              |    2 +-
>   hw/timer/mc146818rtc.c             |    4 +-
>   hw/virtio/virtio-balloon.c         |    2 +-
>   hw/watchdog/watchdog.c             |    2 +-
>   include/hw/qdev-properties.h       |    3 +-
>   include/monitor/monitor.h          |    2 +-
>   include/sysemu/arch_init.h         |    2 +-
>   include/sysemu/balloon.h           |    2 +-
>   include/sysemu/dump.h              |    2 +-
>   include/sysemu/hostmem.h           |    2 +-
>   include/sysemu/replay.h            |    3 +-
>   iothread.c                         |    2 +-
>   migration/savevm.c                 |    3 +-
>   numa.c                             |    4 +-

Mostly mechanical,

>   qapi-schema.json                   | 3098 +-----------------------------------
>   qapi/misc.json                     | 3090 +++++++++++++++++++++++++++++++++++

A huge move of content (git won't flag it as a rename, though ;(

But why is the new file smaller than what was removed from the old file? 
  Let's see...[1]

>   qapi/run-state.json                |   10 +
>   qdev-monitor.c                     |    2 +-
>   qmp.c                              |    4 +-
>   stubs/uuid.c                       |    2 +-
>   stubs/vmgenid.c                    |    2 +-
>   stubs/xen-hvm.c                    |    2 +-
>   target/arm/monitor.c               |    3 +-
>   target/i386/cpu.c                  |    4 +-
>   tests/qmp-test.c                   |    3 +-
>   tests/test-qobject-input-visitor.c |    2 +-
>   tests/test-visitor-serialization.c |    1 -
>   ui/gtk.c                           |    2 +-
>   util/qemu-config.c                 |    2 +-
>   vl.c                               |    4 +-
>   49 files changed, 3181 insertions(+), 3144 deletions(-)
>   create mode 100644 qapi/misc.json

Huge email, but reviewing is not too hard.

> 
> diff --git a/.gitignore b/.gitignore
> index 42c57998fd..7f162e862f 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -38,6 +38,7 @@
>   /qapi/qapi-commands-crypto.[ch]
>   /qapi/qapi-commands-introspect.[ch]
>   /qapi/qapi-commands-migration.[ch]
> +/qapi/qapi-commands-misc.[ch]

If my comments on the earlier patch result in a glob here, you wouldn't 
need these changes.

> --- a/Makefile
> +++ b/Makefile
> @@ -99,6 +99,7 @@ GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c
>   GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c
>   GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c
>   GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c
> +GENERATED_FILES += qapi/qapi-types-misc.h qapi/qapi-types-misc.c
>   GENERATED_FILES += qapi/qapi-types-net.h qapi/qapi-types-net.c
>   GENERATED_FILES += qapi/qapi-types-rocker.h qapi/qapi-types-rocker.c
>   GENERATED_FILES += qapi/qapi-types-run-state.h qapi/qapi-types-run-state.c
> @@ -116,6 +117,7 @@ GENERATED_FILES += qapi/qapi-visit-common.h qapi/qapi-visit-common.c
>   GENERATED_FILES += qapi/qapi-visit-crypto.h qapi/qapi-visit-crypto.c
>   GENERATED_FILES += qapi/qapi-visit-introspect.h qapi/qapi-visit-introspect.c
>   GENERATED_FILES += qapi/qapi-visit-migration.h qapi/qapi-visit-migration.c
> +GENERATED_FILES += qapi/qapi-visit-misc.h qapi/qapi-visit-misc.c

And again, my comments about using intermediate variables and make text 
substitution would result in less duplication here.

> +++ b/Makefile.objs
> @@ -11,6 +11,7 @@ util-obj-y += qapi/qapi-types-common.o
>   util-obj-y += qapi/qapi-types-crypto.o
>   util-obj-y += qapi/qapi-types-introspect.o
>   util-obj-y += qapi/qapi-types-migration.o
> +util-obj-y += qapi/qapi-types-misc.o

and possibly here too.

> +++ b/hmp.c
> @@ -23,13 +23,21 @@
>   #include "qemu/config-file.h"
>   #include "qemu/option.h"
>   #include "qemu/timer.h"
> -#include "qmp-commands.h"
>   #include "qemu/sockets.h"
>   #include "monitor/monitor.h"
>   #include "monitor/qdev.h"
>   #include "qapi/error.h"
>   #include "qapi/opts-visitor.h"
>   #include "qapi-builtin-visit.h"
> +#include "qapi/qapi-commands-block.h"
> +#include "qapi/qapi-commands-char.h"
> +#include "qapi/qapi-commands-migration.h"
> +#include "qapi/qapi-commands-misc.h"
> +#include "qapi/qapi-commands-net.h"
> +#include "qapi/qapi-commands-rocker.h"
> +#include "qapi/qapi-commands-run-state.h"
> +#include "qapi/qapi-commands-tpm.h"
> +#include "qapi/qapi-commands-ui.h"

Well, not every file gets a smaller list of includes ;)

> +++ b/qapi-schema.json
> @@ -92,3100 +92,4 @@
>   { 'include': 'qapi/transaction.json' }
>   { 'include': 'qapi/trace.json' }
>   { 'include': 'qapi/introspect.json' }
> -
> -##
> -# = Miscellanea
> -##

> -# Since: 2.11
> -##
> -{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
> +{ 'include': 'qapi/misc.json' }

[1] Conflict magnet. We'd better be prepared for some rebasing to get 
this patch series through.  See what the last item is here...

> diff --git a/qapi/misc.json b/qapi/misc.json
> new file mode 100644
> index 0000000000..225631bf7d
> --- /dev/null
> +++ b/qapi/misc.json
> @@ -0,0 +1,3090 @@
> +# -*- Mode: Python -*-
> +#
> +

Should we be thinking about copyright/license statements in the QAPI 
submodule files?  But that's a topic for another series.


> +# Since: 2.9
> +##
> +{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
> diff --git a/qapi/run-state.json b/qapi/run-state.json

[1] ...and oops - you already hit one of those conflicts. 
watchdog-set-action disappeared in the move.  Or did it? [2]

> index bca46a8785..a27c3c2a93 100644
> --- a/qapi/run-state.json
> +++ b/qapi/run-state.json
> @@ -283,6 +283,16 @@
>     'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
>               'inject-nmi' ] }
>   
> +
> +##
> +# @watchdog-set-action:
> +#
> +# Set watchdog action
> +#
> +# Since: 2.11
> +##
> +{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
> +

[2] Oh, you MOVED it to a different file.  Let's fix that separately, so 
that THIS patch can be just 1-1 file motion, not 1-N (making rebasing 
easier).

>   ##
>   # @GUEST_PANICKED:
>   #
> diff --git a/qdev-monitor.c b/qdev-monitor.c
> index 846238175f..b8f6bc3f7e 100644
> --- a/qdev-monitor.c

Looks reasonable, but not quite ready for my R-b until v3.

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

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

* Re: [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
@ 2018-02-12 22:27   ` Eric Blake
  2018-02-13 16:00   ` Marc-Andre Lureau
  2018-02-19 19:33   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:27 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> With modular code generation, putting stuff right into
> qapi-schema.json is a bad idea.  Update writing-qmp-commands.txt
> accordingly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   docs/devel/writing-qmp-commands.txt | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
@ 2018-02-12 22:29   ` Eric Blake
  2018-02-13 16:03   ` Marc-Andre Lureau
  2018-02-19 19:35   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:29 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> * Fix guidance on error classes
> 
> * Point to generated documentation
> 
> * Drop plea for documentation, because the QAPI code generator
>    enforces it since commit 3313b6124b
> 
> * Minor tweaks here and there
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   docs/devel/writing-qmp-commands.txt | 25 +++++++++----------------
>   docs/interop/qmp-intro.txt          |  3 ++-
>   2 files changed, 11 insertions(+), 17 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
@ 2018-02-12 22:36   ` Eric Blake
  2018-02-23 17:51     ` Markus Armbruster
  2018-02-13 16:08   ` Marc-Andre Lureau
  2018-02-19 19:37   ` Michael Roth
  2 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:36 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> Move qapi-schema.json to qapi/, so it's next to its modules, and all
> files get generated to qapi/, not just the ones generated for modules.
> 
> Consistently name the generated files qapi-MODULE.EXT:
> qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become
> qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch].
> This gets rid of the temporary hacks in scripts/qapi/commands.py and
> scripts/qapi/events.py.

Ah, so my parallel series that proposed naming the file 
qapi/qmp-schema.qapi gets interesting, with your patch favoring the 
qapi- naming everywhere.  I'll have to think about how much (or little) 
of my series to rebase on top of this (I like my notion of renaming to 
the .qapi suffix, though, as we really are using files that aren't JSON, 
but only resemble it).

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

> +++ b/.gitignore
> @@ -29,8 +29,8 @@
>   /qga/qapi-generated
>   /qapi-generated
>   /qapi-gen-timestamp
> -/qapi-builtin-types.[ch]
> -/qapi-builtin-visit.[ch]
> +/qapi/qapi-builtin-types.[ch]
> +/qapi/qapi-builtin-visit.[ch]

Might be some interesting churn if you like my idea of using globs for 
easier maintenance of this file.

> +++ b/tpm.c
> @@ -182,7 +182,6 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
>   
>   /*
>    * Walk the list of active TPM backends and collect information about them
> - * following the schema description in qapi-schema.json.
>    */

Should the overall comment keep the trailing '.'?

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
@ 2018-02-12 22:47   ` Eric Blake
  2018-02-13 16:12   ` Marc-Andre Lureau
  2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:47 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> Fix up the reference to qmp-commands.hx in qmp.c.  Missed in commit
> 5032a16d1d.
> 
> Fix up the reference to qmp-commands.txt in
> docs/xen-save-devices-state.txt.  Missed in commit 4d8bb958fa.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   docs/xen-save-devices-state.txt |  3 +--
>   qmp.c                           | 14 +++++++-------
>   2 files changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt
> index a72ecc8081..1912ecad25 100644
> --- a/docs/xen-save-devices-state.txt
> +++ b/docs/xen-save-devices-state.txt
> @@ -8,8 +8,7 @@ These operations are normally used with migration (see migration.txt),
>   however it is also possible to save the state of all devices to file,
>   without saving the RAM or the block devices of the VM.
>   
> -This operation is called "xen-save-devices-state" (see
> -qmp-commands.txt)
> +The save operation is available as QMP command xen-save-devices-state.

I like the fact that you made the reword more generic (in case we rename 
things again, one less place to edit).

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
@ 2018-02-12 22:48   ` Eric Blake
  2018-02-13 16:15   ` Marc-Andre Lureau
  2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-12 22:48 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:36 AM, Markus Armbruster wrote:
> We used to generate first test and later QGA QAPI code into
> qapi-generated/.  Commit b93b63f574 moved the test code to tests/.
> Commit 54c2e50205 moved the QGA code to qga/qapi-generated/.  The
> directory has been unused since.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>   .gitignore | 1 -
>   Makefile   | 1 -
>   configure  | 1 -
>   3 files changed, 3 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* Re: [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
  2018-02-12 19:48   ` Eric Blake
@ 2018-02-13 15:22     ` Marc-Andre Lureau
  2018-02-23 17:22       ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:22 UTC (permalink / raw)
  To: Eric Blake; +Cc: Markus Armbruster, qemu-devel, Michael Roth, marcandre

Hi

On Mon, Feb 12, 2018 at 8:48 PM, Eric Blake <eblake@redhat.com> wrote:
> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>>
>> A massive number of objects depends on QAPI-generated headers.  In my
>> "build everything" tree, it's roughly 4800 out of 5100.  This is
>> particularly annoying when only some of the generated files change,
>> say for a doc fix.
>>
>> Improve qapi-gen.py to touch its output files only if they actually
>> change.  Rebuild time for a QAPI doc fix drops from many minutes to a
>> few seconds.  Rebuilds get faster for certain code changes, too.  For
>> instance, adding a simple QMP event now recompiles less than 200
>> instead of 4800 objects.  But adding a QAPI type is as bad as ever;
>> we've clearly got more work to do.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> ---
>>   scripts/qapi/common.py | 11 +++++++++--
>>   1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index 8290795dc1..2e58573a39 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -1951,9 +1951,16 @@ class QAPIGen(object):
>>               except os.error as e:
>>                   if e.errno != errno.EEXIST:
>>                       raise
>> -        f = open(os.path.join(output_dir, fname), 'w')
>> -        f.write(self._top(fname) + self._preamble + self._body
>> +        fd = os.open(os.path.join(output_dir, fname),
>> +                     os.O_RDWR | os.O_CREAT, 0666)
>
>
> patchew complained here for mingw; I'm not sure why.

python3 syntax error.
https://stackoverflow.com/questions/1837874/invalid-token-when-using-octal-numbers

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

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

* Re: [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
  2018-02-12 16:55   ` Eric Blake
@ 2018-02-13 15:24   ` Marc-Andre Lureau
  1 sibling, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:24 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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


> ---
>  block.c                 | 1 -
>  block/qcow2.c           | 1 -
>  chardev/char-fe.c       | 1 +
>  chardev/char.c          | 1 +
>  qom/object_interfaces.c | 1 +
>  scripts/qapi-visit.py   | 2 +-
>  6 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/block.c b/block.c
> index f94585b230..05a484b4b8 100644
> --- a/block.c
> +++ b/block.c
> @@ -32,7 +32,6 @@
>  #include "qemu/module.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> -#include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qjson.h"
>  #include "qapi/qmp/qstring.h"
>  #include "sysemu/block-backend.h"
> diff --git a/block/qcow2.c b/block/qcow2.c
> index a64a572785..9245deac19 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -30,7 +30,6 @@
>  #include "block/qcow2.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
> -#include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi-event.h"
> diff --git a/chardev/char-fe.c b/chardev/char-fe.c
> index c611b3fa3e..e5f870e4d2 100644
> --- a/chardev/char-fe.c
> +++ b/chardev/char-fe.c
> @@ -24,6 +24,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
>  #include "qapi-visit.h"
>  #include "sysemu/replay.h"
>
> diff --git a/chardev/char.c b/chardev/char.c
> index 01d979a1da..c9a4da5516 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -32,6 +32,7 @@
>  #include "qmp-commands.h"
>  #include "qapi-visit.h"
>  #include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
>  #include "sysemu/replay.h"
>  #include "qemu/help_option.h"
>  #include "qemu/option.h"
> diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
> index 80d09139be..43d9aa0946 100644
> --- a/qom/object_interfaces.c
> +++ b/qom/object_interfaces.c
> @@ -1,6 +1,7 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> +#include "qapi/qmp/qerror.h"
>  #include "qom/object_interfaces.h"
>  #include "qemu/module.h"
>  #include "qemu/option.h"
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 7e1cfc13f0..bc2b8b581a 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -371,13 +371,13 @@ fdef.write(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
>                   prefix=prefix))
>
>  fdecl.write(mcgen('''
>  #include "qapi/visitor.h"
> -#include "qapi/qmp/qerror.h"
>  #include "%(prefix)sqapi-types.h"
>
>  ''',
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
  2018-02-12 16:59   ` Eric Blake
@ 2018-02-13 15:24   ` Marc-Andre Lureau
  2018-02-16 22:56   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:24 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Rename the variable holding the QAPISchemaGenFOOVisitor from gen to
> vis, to avoid confusion in the next commit.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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


> ---
>  scripts/qapi-commands.py   | 8 ++++----
>  scripts/qapi-event.py      | 8 ++++----
>  scripts/qapi-introspect.py | 8 ++++----
>  scripts/qapi-types.py      | 8 ++++----
>  scripts/qapi-visit.py      | 8 ++++----
>  5 files changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 84a980d882..c3aa52fce1 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -291,9 +291,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>                    prefix=prefix, c_prefix=c_name(prefix, protect=False)))
>
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenCommandVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenCommandVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
>
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index 0a098803e2..edb9ddb650 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -203,9 +203,9 @@ fdecl.write(mcgen('''
>  event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
>
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenEventVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenEventVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
>
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index bd9253a172..ebe8706f41 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -193,9 +193,9 @@ fdef.write(mcgen('''
>                   prefix=prefix))
>
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
>
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index 1103dbda2d..4db8424da1 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -273,9 +273,9 @@ fdecl.write(mcgen('''
>  '''))
>
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenTypeVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenTypeVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
>
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index e56b3c1256..3c1a0e2544 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -360,9 +360,9 @@ fdecl.write(mcgen('''
>                    prefix=prefix))
>
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenVisitVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenVisitVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
>
>  close_output(fdef, fdecl)
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
  2018-02-12 19:44   ` Eric Blake
@ 2018-02-13 15:24   ` Marc-Andre Lureau
  2018-02-18 22:31   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:24 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> argparse is nicer to use than getopt, and gives us --help almost for
> free.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

nice,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>


> ---
>  scripts/qapi-gen.py    | 48 ++++++++++++++++++++++++++++++------------------
>  scripts/qapi/common.py | 43 -------------------------------------------
>  2 files changed, 30 insertions(+), 61 deletions(-)
>
> diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
> index 2100ca1145..e5be484e3e 100755
> --- a/scripts/qapi-gen.py
> +++ b/scripts/qapi-gen.py
> @@ -4,8 +4,11 @@
>  # This work is licensed under the terms of the GNU GPL, version 2 or later.
>  # See the COPYING file in the top-level directory.
>
> +from __future__ import print_function
> +import argparse
> +import re
>  import sys
> -from qapi.common import parse_command_line, QAPISchema
> +from qapi.common import QAPISchema
>  from qapi.types import gen_types
>  from qapi.visit import gen_visit
>  from qapi.commands import gen_commands
> @@ -15,26 +18,35 @@ from qapi.doc import gen_doc
>
>
>  def main(argv):
> -    (input_file, output_dir, prefix, opts) = \
> -        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
> +    parser = argparse.ArgumentParser(
> +        description='Generate code from a QAPI schema')
> +    parser.add_argument('-b', '--builtins', action='store_true',
> +                        help="generate code for built-in types")
> +    parser.add_argument('-o', '--output_dir', action='store', default='',
> +                        help="write output to directory OUTPUT_DIR")
> +    parser.add_argument('-p', '--prefix', action='store', default='',
> +                        help="prefix for symbols")
> +    parser.add_argument('-u', '--unmask-non-abi-names', action='store_true',
> +                        dest='unmask',
> +                        help="expose non-ABI names in introspection")
> +    parser.add_argument('schema', action='store')
> +    args = parser.parse_args()
>
> -    opt_builtins = False
> -    opt_unmask = False
> +    match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', args.prefix)
> +    if match.end() != len(args.prefix):
> +        print("%s: 'funny character '%s' in argument of --prefix"
> +              % (sys.argv[0], args.prefix[match.end()]),
> +              file=sys.stderr)
> +        sys.exit(1)
>
> -    for o, a in opts:
> -        if o in ('-b', '--builtins'):
> -            opt_builtins = True
> -        if o in ('-u', '--unmask-non-abi-names'):
> -            opt_unmask = True
> +    schema = QAPISchema(args.schema)
>
> -    schema = QAPISchema(input_file)
> -
> -    gen_types(schema, output_dir, prefix, opt_builtins)
> -    gen_visit(schema, output_dir, prefix, opt_builtins)
> -    gen_commands(schema, output_dir, prefix)
> -    gen_events(schema, output_dir, prefix)
> -    gen_introspect(schema, output_dir, prefix, opt_unmask)
> -    gen_doc(schema, output_dir, prefix)
> +    gen_types(schema, args.output_dir, args.prefix, args.builtins)
> +    gen_visit(schema, args.output_dir, args.prefix, args.builtins)
> +    gen_commands(schema, args.output_dir, args.prefix)
> +    gen_events(schema, args.output_dir, args.prefix)
> +    gen_introspect(schema, args.output_dir, args.prefix, args.unmask)
> +    gen_doc(schema, args.output_dir, args.prefix)
>
>
>  if __name__ == '__main__':
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 868ec25deb..8290795dc1 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -13,7 +13,6 @@
>
>  from __future__ import print_function
>  import errno
> -import getopt
>  import os
>  import re
>  import string
> @@ -1924,48 +1923,6 @@ def build_params(arg_type, boxed, extra):
>
>
>  #
> -# Common command line parsing
> -#
> -
> -
> -def parse_command_line(extra_options='', extra_long_options=[]):
> -
> -    try:
> -        opts, args = getopt.gnu_getopt(sys.argv[1:],
> -                                       'p:o:' + extra_options,
> -                                       ['prefix=', 'output-dir=']
> -                                       + extra_long_options)
> -    except getopt.GetoptError as err:
> -        print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
> -        sys.exit(1)
> -
> -    output_dir = ''
> -    prefix = ''
> -    extra_opts = []
> -
> -    for oa in opts:
> -        o, a = oa
> -        if o in ('-p', '--prefix'):
> -            match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
> -            if match.end() != len(a):
> -                print("%s: 'funny character '%s' in argument of --prefix" \
> -                      % (sys.argv[0], a[match.end()]), file=sys.stderr)
> -                sys.exit(1)
> -            prefix = a
> -        elif o in ('-o', '--output-dir'):
> -            output_dir = a + '/'
> -        else:
> -            extra_opts.append(oa)
> -
> -    if len(args) != 1:
> -        print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
> -        sys.exit(1)
> -    fname = args[0]
> -
> -    return (fname, output_dir, prefix, extra_opts)
> -
> -
> -#
>  # Accumulate and write output
>  #
>
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
  2018-02-12 20:56   ` Eric Blake
@ 2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19  0:21   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:25 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> All generated .c are named like their .h, except for qmp-marshal.c and
> qmp-commands.h.  To add to the confusion, tests-qmp-commands.c falsely
> matches generated test-qmp-commands.h.
>
> Get rid of this unnecessary complication.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

that makes more sense,

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


> ---
>  .gitignore                                     |  3 +--
>  Makefile                                       |  6 +++---
>  Makefile.objs                                  |  2 +-
>  docs/devel/qapi-code-gen.txt                   |  6 +++---
>  qga/Makefile.objs                              |  2 +-
>  scripts/qapi/commands.py                       |  2 +-
>  tests/.gitignore                               |  5 ++---
>  tests/Makefile.include                         | 10 +++++-----
>  tests/{test-qmp-commands.c => test-qmp-cmds.c} |  0
>  9 files changed, 17 insertions(+), 19 deletions(-)
>  rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (100%)
>
> diff --git a/.gitignore b/.gitignore
> index 2f9a92f6cc..7d783e6e66 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -33,9 +33,8 @@
>  /qapi-visit.[ch]
>  /qapi-event.[ch]
>  /qapi-doc.texi
> -/qmp-commands.h
> +/qmp-commands.[ch]
>  /qmp-introspect.[ch]
> -/qmp-marshal.c
>  /qemu-doc.html
>  /qemu-doc.info
>  /qemu-doc.txt
> diff --git a/Makefile b/Makefile
> index bd781c6aad..164a38578e 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -91,7 +91,7 @@ include $(SRC_PATH)/rules.mak
>
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
>  GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> -GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
> +GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
>  GENERATED_FILES += qmp-introspect.h
>  GENERATED_FILES += qmp-introspect.c
>  GENERATED_FILES += qapi-doc.texi
> @@ -496,7 +496,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
>
>  qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
>  qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
> -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \
> +qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
>  qga/qapi-generated/qga-qapi-doc.texi: \
>  qga/qapi-generated/qapi-gen-timestamp ;
>  qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
> @@ -522,7 +522,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>
>  qapi-types.c qapi-types.h \
>  qapi-visit.c qapi-visit.h \
> -qmp-commands.h qmp-marshal.c \
> +qmp-commands.h qmp-commands.c \
>  qapi-event.c qapi-event.h \
>  qmp-introspect.h qmp-introspect.c \
>  qapi-doc.texi: \
> diff --git a/Makefile.objs b/Makefile.objs
> index 2efba6d768..d255aaf194 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -78,7 +78,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
>  ######################################################################
>  # qapi
>
> -common-obj-y += qmp-marshal.o
> +common-obj-y += qmp-commands.o
>  common-obj-y += qmp-introspect.o
>  common-obj-y += qmp.o hmp.o
>  endif
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index 1a1cbaea7b..ba1dc73298 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -1147,8 +1147,8 @@ declares qmp_COMMAND() that the user must implement.
>
>  The following files are generated:
>
> -$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each
> -                        QMP command defined in the schema
> +$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
> +                         QMP command defined in the schema
>
>  $(prefix)qmp-commands.h: Function prototypes for the QMP commands
>                           specified in the schema
> @@ -1170,7 +1170,7 @@ Example:
>      void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
>
>      #endif
> -    $ cat qapi-generated/example-qmp-marshal.c
> +    $ cat qapi-generated/example-qmp-commands.c
>  [Uninteresting stuff omitted...]
>
>      static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
> diff --git a/qga/Makefile.objs b/qga/Makefile.objs
> index 1c5986c0bb..6151378ae4 100644
> --- a/qga/Makefile.objs
> +++ b/qga/Makefile.objs
> @@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
>  qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
>  qga-obj-$(CONFIG_WIN32) += vss-win32.o
>  qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
> -qga-obj-y += qapi-generated/qga-qmp-marshal.o
> +qga-obj-y += qapi-generated/qga-qmp-commands.o
>
>  qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index a744611d58..05fe33a03b 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -289,5 +289,5 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qmp-marshal.c')
> +    genc.write(output_dir, prefix + 'qmp-commands.c')
>      genh.write(output_dir, prefix + 'qmp-commands.h')
> diff --git a/tests/.gitignore b/tests/.gitignore
> index e5c744b7ed..2629cfc2f9 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -70,13 +70,12 @@ test-qdist
>  test-qga
>  test-qht
>  test-qht-par
> -test-qmp-commands
> -test-qmp-commands.h
> +test-qmp-cmds
> +test-qmp-commands.[ch]
>  test-qmp-event
>  test-qobject-input-strict
>  test-qobject-input-visitor
>  test-qmp-introspect.[ch]
> -test-qmp-marshal.c
>  test-qobject-output-visitor
>  test-rcu-list
>  test-replication
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index b406531b34..9a21ed7ee9 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -61,8 +61,8 @@ check-unit-y += tests/test-clone-visitor$(EXESUF)
>  gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
>  check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
>  gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
> -check-unit-y += tests/test-qmp-commands$(EXESUF)
> -gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
> +check-unit-y += tests/test-qmp-cmds$(EXESUF)
> +gcov-files-test-qmp-cmds-y = qapi/qmp-dispatch.c
>  check-unit-y += tests/test-string-input-visitor$(EXESUF)
>  gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
>  check-unit-y += tests/test-string-output-visitor$(EXESUF)
> @@ -576,7 +576,7 @@ test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
>         tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
>         tests/test-clone-visitor.o \
>         tests/test-qobject-input-visitor.o \
> -       tests/test-qmp-commands.o tests/test-visitor-serialization.o \
> +       tests/test-qmp-cmds.o tests/test-visitor-serialization.o \
>         tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
>         tests/test-opts-visitor.o tests/test-qmp-event.o \
>         tests/rcutorture.o tests/test-rcu-list.o \
> @@ -656,7 +656,7 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
>
>  tests/test-qapi-types.c tests/test-qapi-types.h \
>  tests/test-qapi-visit.c tests/test-qapi-visit.h \
> -tests/test-qmp-commands.h tests/test-qmp-marshal.c \
> +tests/test-qmp-commands.h tests/test-qmp-commands.c \
>  tests/test-qapi-event.c tests/test-qapi-event.h \
>  tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
>  tests/test-qapi-gen-timestamp ;
> @@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
>  tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
>  tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
>  tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
> -tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
> +tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
>  tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
>  tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
>
> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-cmds.c
> similarity index 100%
> rename from tests/test-qmp-commands.c
> rename to tests/test-qmp-cmds.c
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
  2018-02-12 21:06   ` Eric Blake
@ 2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19 15:52   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:25 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> The use of QAPIGen is rather shallow so far: most of the output
> accumulation is not converted.  Take the next step: convert output
> accumulation in the code-generating visitor classes.  Helper functions
> outside these classes are not converted.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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


> ---
>  scripts/qapi/commands.py   | 71 ++++++++++++++++------------------------
>  scripts/qapi/common.py     | 13 ++++++++
>  scripts/qapi/doc.py        | 74 ++++++++++++++++++++----------------------
>  scripts/qapi/events.py     | 55 ++++++++++++-------------------
>  scripts/qapi/introspect.py | 56 +++++++++++++-------------------
>  scripts/qapi/types.py      | 81 +++++++++++++++++++---------------------------
>  scripts/qapi/visit.py      | 80 +++++++++++++++++++--------------------------
>  7 files changed, 188 insertions(+), 242 deletions(-)
>
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index 05fe33a03b..46757db771 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -223,44 +223,15 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
>      return ret
>
>
> -class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> +class QAPISchemaGenCommandVisitor(QAPISchemaMonolithicCVisitor):
> +
>      def __init__(self, prefix):
> -        self._prefix = prefix
> -        self.decl = None
> -        self.defn = None
> -        self._regy = None
> -        self._visited_ret_types = None
> -
> -    def visit_begin(self, schema):
> -        self.decl = ''
> -        self.defn = ''
> +        QAPISchemaMonolithicCVisitor.__init__(
> +            self, prefix, 'qmp-commands',
> +            ' * Schema-defined QAPI/QMP commands', __doc__)
>          self._regy = ''
>          self._visited_ret_types = set()
> -
> -    def visit_end(self):
> -        self.defn += gen_registry(self._regy, self._prefix)
> -        self._regy = None
> -        self._visited_ret_types = None
> -
> -    def visit_command(self, name, info, arg_type, ret_type,
> -                      gen, success_response, boxed):
> -        if not gen:
> -            return
> -        self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
> -        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)
> -
> -
> -def gen_commands(schema, output_dir, prefix):
> -    blurb = ' * Schema-defined QAPI/QMP commands'
> -    genc = QAPIGenC(blurb, __doc__)
> -    genh = QAPIGenH(blurb, __doc__)
> -
> -    genc.add(mcgen('''
> +        self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qemu/module.h"
> @@ -275,19 +246,33 @@ def gen_commands(schema, output_dir, prefix):
>  #include "%(prefix)sqmp-commands.h"
>
>  ''',
> -                   prefix=prefix))
> -
> -    genh.add(mcgen('''
> +                             prefix=prefix))
> +        self._genh.add(mcgen('''
>  #include "%(prefix)sqapi-types.h"
>  #include "qapi/qmp/dispatch.h"
>
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
> -                   prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> +                             prefix=prefix,
> +                             c_prefix=c_name(prefix, protect=False)))
>
> +    def visit_end(self):
> +        self._genc.add(gen_registry(self._regy, self._prefix))
> +
> +    def visit_command(self, name, info, arg_type, ret_type,
> +                      gen, success_response, boxed):
> +        if not gen:
> +            return
> +        self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
> +        if ret_type and ret_type not in self._visited_ret_types:
> +            self._visited_ret_types.add(ret_type)
> +            self._genc.add(gen_marshal_output(ret_type))
> +        self._genh.add(gen_marshal_decl(name))
> +        self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
> +        self._regy += gen_register_command(name, success_response)
> +
> +
> +def gen_commands(schema, output_dir, prefix):
>      vis = QAPISchemaGenCommandVisitor(prefix)
>      schema.visit(vis)
> -    genc.add(vis.defn)
> -    genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qmp-commands.c')
> -    genh.write(output_dir, prefix + 'qmp-commands.h')
> +    vis.write(output_dir)
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 29d98ca934..31d2f73e7e 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -2049,3 +2049,16 @@ class QAPIGenDoc(QAPIGen):
>      def _top(self, fname):
>          return (QAPIGen._top(self, fname)
>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
> +
> +
> +class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
> +
> +    def __init__(self, prefix, what, blurb, pydoc):
> +        self._prefix = prefix
> +        self._what = what
> +        self._genc = QAPIGenC(blurb, pydoc)
> +        self._genh = QAPIGenH(blurb, pydoc)
> +
> +    def write(self, output_dir):
> +        self._genc.write(output_dir, self._prefix + self._what + '.c')
> +        self._genh.write(output_dir, self._prefix + self._what + '.h')
> diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
> index cc4d5a43fb..0ea68bf813 100644
> --- a/scripts/qapi/doc.py
> +++ b/scripts/qapi/doc.py
> @@ -197,33 +197,35 @@ def texi_entity(doc, what, base=None, variants=None,
>
>
>  class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
> -    def __init__(self):
> -        self.out = None
> +    def __init__(self, prefix):
> +        self._prefix = prefix
> +        self._gen = qapi.common.QAPIGenDoc()
>          self.cur_doc = None
>
> -    def visit_begin(self, schema):
> -        self.out = ''
> +    def write(self, output_dir):
> +        self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
>
>      def visit_enum_type(self, name, info, values, prefix):
>          doc = self.cur_doc
> -        self.out += TYPE_FMT(type='Enum',
> -                             name=doc.symbol,
> -                             body=texi_entity(doc, 'Values',
> -                                              member_func=texi_enum_value))
> +        self._gen.add(TYPE_FMT(type='Enum',
> +                               name=doc.symbol,
> +                               body=texi_entity(doc, 'Values',
> +                                                member_func=texi_enum_value)))
>
>      def visit_object_type(self, name, info, base, members, variants):
>          doc = self.cur_doc
>          if base and base.is_implicit():
>              base = None
> -        self.out += TYPE_FMT(type='Object',
> -                             name=doc.symbol,
> -                             body=texi_entity(doc, 'Members', base, variants))
> +        self._gen.add(TYPE_FMT(type='Object',
> +                               name=doc.symbol,
> +                               body=texi_entity(doc, 'Members',
> +                                                base, variants)))
>
>      def visit_alternate_type(self, name, info, variants):
>          doc = self.cur_doc
> -        self.out += TYPE_FMT(type='Alternate',
> -                             name=doc.symbol,
> -                             body=texi_entity(doc, 'Members'))
> +        self._gen.add(TYPE_FMT(type='Alternate',
> +                               name=doc.symbol,
> +                               body=texi_entity(doc, 'Members')))
>
>      def visit_command(self, name, info, arg_type, ret_type,
>                        gen, success_response, boxed):
> @@ -235,44 +237,38 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>              body += texi_sections(doc)
>          else:
>              body = texi_entity(doc, 'Arguments')
> -        self.out += MSG_FMT(type='Command',
> -                            name=doc.symbol,
> -                            body=body)
> +        self._gen.add(MSG_FMT(type='Command',
> +                              name=doc.symbol,
> +                              body=body))
>
>      def visit_event(self, name, info, arg_type, boxed):
>          doc = self.cur_doc
> -        self.out += MSG_FMT(type='Event',
> -                            name=doc.symbol,
> -                            body=texi_entity(doc, 'Arguments'))
> +        self._gen.add(MSG_FMT(type='Event',
> +                              name=doc.symbol,
> +                              body=texi_entity(doc, 'Arguments')))
>
>      def symbol(self, doc, entity):
> -        if self.out:
> -            self.out += '\n'
> +        if self._gen._body:
> +            self._gen.add('\n')
>          self.cur_doc = doc
>          entity.visit(self)
>          self.cur_doc = None
>
>      def freeform(self, doc):
>          assert not doc.args
> -        if self.out:
> -            self.out += '\n'
> -        self.out += texi_body(doc) + texi_sections(doc)
> +        if self._gen._body:
> +            self._gen.add('\n')
> +        self._gen.add(texi_body(doc) + texi_sections(doc))
>
>
> -def texi_schema(schema):
> -    """Convert QAPI schema documentation to Texinfo"""
> -    gen = QAPISchemaGenDocVisitor()
> -    gen.visit_begin(schema)
> +def gen_doc(schema, output_dir, prefix):
> +    if not qapi.common.doc_required:
> +        return
> +    vis = QAPISchemaGenDocVisitor(prefix)
> +    vis.visit_begin(schema)
>      for doc in schema.docs:
>          if doc.symbol:
> -            gen.symbol(doc, schema.lookup_entity(doc.symbol))
> +            vis.symbol(doc, schema.lookup_entity(doc.symbol))
>          else:
> -            gen.freeform(doc)
> -    return gen.out
> -
> -
> -def gen_doc(schema, output_dir, prefix):
> -    if qapi.common.doc_required:
> -        gen = qapi.common.QAPIGenDoc()
> -        gen.add(texi_schema(schema))
> -        gen.write(output_dir, prefix + 'qapi-doc.texi')
> +            vis.freeform(doc)
> +    vis.write(output_dir)
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index b7dc82004f..81ab3abb30 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -148,35 +148,15 @@ out:
>      return ret
>
>
> -class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
> +class QAPISchemaGenEventVisitor(QAPISchemaMonolithicCVisitor):
> +
>      def __init__(self, prefix):
> +        QAPISchemaMonolithicCVisitor.__init__(
> +            self, prefix, 'qapi-event',
> +            ' * Schema-defined QAPI/QMP events', __doc__)
>          self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
> -        self.decl = None
> -        self.defn = None
> -        self._event_names = None
> -
> -    def visit_begin(self, schema):
> -        self.decl = ''
> -        self.defn = ''
>          self._event_names = []
> -
> -    def visit_end(self):
> -        self.decl += gen_enum(self._enum_name, self._event_names)
> -        self.defn += gen_enum_lookup(self._enum_name, self._event_names)
> -        self._event_names = None
> -
> -    def visit_event(self, name, info, arg_type, boxed):
> -        self.decl += gen_event_send_decl(name, arg_type, boxed)
> -        self.defn += gen_event_send(name, arg_type, boxed, self._enum_name)
> -        self._event_names.append(name)
> -
> -
> -def gen_events(schema, output_dir, prefix):
> -    blurb = ' * Schema-defined QAPI/QMP events'
> -    genc = QAPIGenC(blurb, __doc__)
> -    genh = QAPIGenH(blurb, __doc__)
> -
> -    genc.add(mcgen('''
> +        self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "%(prefix)sqapi-event.h"
> @@ -187,18 +167,25 @@ def gen_events(schema, output_dir, prefix):
>  #include "qapi/qmp-event.h"
>
>  ''',
> -                   prefix=prefix))
> -
> -    genh.add(mcgen('''
> +                             prefix=prefix))
> +        self._genh.add(mcgen('''
>  #include "qapi/util.h"
>  #include "%(prefix)sqapi-types.h"
>
>  ''',
> -                   prefix=prefix))
> +                             prefix=prefix))
>
> +    def visit_end(self):
> +        self._genh.add(gen_enum(self._enum_name, self._event_names))
> +        self._genc.add(gen_enum_lookup(self._enum_name, self._event_names))
> +
> +    def visit_event(self, name, info, arg_type, boxed):
> +        self._genh.add(gen_event_send_decl(name, arg_type, boxed))
> +        self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
> +        self._event_names.append(name)
> +
> +
> +def gen_events(schema, output_dir, prefix):
>      vis = QAPISchemaGenEventVisitor(prefix)
>      schema.visit(vis)
> -    genc.add(vis.defn)
> -    genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qapi-event.c')
> -    genh.write(output_dir, prefix + 'qapi-event.h')
> +    vis.write(output_dir)
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index 1e4f065164..f571cc134c 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -40,22 +40,26 @@ def to_c_string(string):
>      return '"' + string.replace('\\', r'\\').replace('"', r'\"') + '"'
>
>
> -class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
> +class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
> +
>      def __init__(self, prefix, unmask):
> -        self._prefix = prefix
> +        QAPISchemaMonolithicCVisitor.__init__(
> +            self, prefix, 'qmp-introspect',
> +            ' * QAPI/QMP schema introspection', __doc__)
>          self._unmask = unmask
> -        self.defn = None
> -        self.decl = None
>          self._schema = None
> -        self._jsons = None
> -        self._used_types = None
> -        self._name_map = None
> +        self._jsons = []
> +        self._used_types = []
> +        self._name_map = {}
> +        self._genc.add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "%(prefix)sqmp-introspect.h"
> +
> +''',
> +                             prefix=prefix))
>
>      def visit_begin(self, schema):
>          self._schema = schema
> -        self._jsons = []
> -        self._used_types = []
> -        self._name_map = {}
>
>      def visit_end(self):
>          # visit the types that are actually used
> @@ -67,21 +71,21 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
>          # TODO can generate awfully long lines
>          jsons.extend(self._jsons)
>          name = c_name(self._prefix, protect=False) + 'qmp_schema_json'
> -        self.decl = mcgen('''
> +        self._genh.add(mcgen('''
>  extern const char %(c_name)s[];
>  ''',
> -                          c_name=c_name(name))
> +                             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('''
> +        self._genc.add(mcgen('''
>  const char %(c_name)s[] = %(c_string)s;
>  ''',
> -                          c_name=c_name(name),
> -                          c_string=c_string)
> +                             c_name=c_name(name),
> +                             c_string=c_string))
>          self._schema = None
> -        self._jsons = None
> -        self._used_types = None
> -        self._name_map = None
> +        self._jsons = []
> +        self._used_types = []
> +        self._name_map = {}
>
>      def visit_needed(self, entity):
>          # Ignore types on first pass; visit_end() will pick up used types
> @@ -169,20 +173,6 @@ const char %(c_name)s[] = %(c_string)s;
>
>
>  def gen_introspect(schema, output_dir, prefix, opt_unmask):
> -    blurb = ' * QAPI/QMP schema introspection'
> -    genc = QAPIGenC(blurb, __doc__)
> -    genh = QAPIGenH(blurb, __doc__)
> -
> -    genc.add(mcgen('''
> -#include "qemu/osdep.h"
> -#include "%(prefix)sqmp-introspect.h"
> -
> -''',
> -                   prefix=prefix))
> -
>      vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
>      schema.visit(vis)
> -    genc.add(vis.defn)
> -    genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qmp-introspect.c')
> -    genh.write(output_dir, prefix + 'qmp-introspect.h')
> +    vis.write(output_dir)
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index aa3c01e750..d2b8423479 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -167,36 +167,41 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
>      return ret
>
>
> -class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
> -    def __init__(self, opt_builtins):
> +class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
> +
> +    def __init__(self, prefix, opt_builtins):
> +        QAPISchemaMonolithicCVisitor.__init__(
> +            self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
> +            __doc__)
>          self._opt_builtins = opt_builtins
> -        self.decl = None
> -        self.defn = None
> -        self._fwdecl = None
> -        self._btin = None
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qapi/dealloc-visitor.h"
> +#include "%(prefix)sqapi-types.h"
> +#include "%(prefix)sqapi-visit.h"
> +''',
> +                                      prefix=prefix))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/util.h"
> +'''))
> +        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
>
>      def visit_begin(self, schema):
>          # gen_object() is recursive, ensure it doesn't visit the empty type
>          objects_seen.add(schema.the_empty_object_type.name)
> -        self.decl = ''
> -        self.defn = ''
> -        self._fwdecl = ''
> -        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
>
>      def visit_end(self):
> -        self.decl = self._fwdecl + self.decl
> -        self._fwdecl = None
>          # To avoid header dependency hell, we always generate
>          # declarations for built-in types in our header files and
>          # simply guard them.  See also opt_builtins (command line
>          # option -b).
>          self._btin += guardend('QAPI_TYPES_BUILTIN')
> -        self.decl = self._btin + self.decl
> +        self._genh.preamble_add(self._btin)
>          self._btin = None
>
>      def _gen_type_cleanup(self, name):
> -        self.decl += gen_type_cleanup_decl(name)
> -        self.defn += gen_type_cleanup(name)
> +        self._genh.add(gen_type_cleanup_decl(name))
> +        self._genc.add(gen_type_cleanup(name))
>
>      def visit_enum_type(self, name, info, values, prefix):
>          # Special case for our lone builtin enum type
> @@ -204,10 +209,10 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          if not info:
>              self._btin += gen_enum(name, values, prefix)
>              if self._opt_builtins:
> -                self.defn += gen_enum_lookup(name, values, prefix)
> +                self._genc.add(gen_enum_lookup(name, values, prefix))
>          else:
> -            self._fwdecl += gen_enum(name, values, prefix)
> -            self.defn += gen_enum_lookup(name, values, prefix)
> +            self._genh.preamble_add(gen_enum(name, values, prefix))
> +            self._genc.add(gen_enum_lookup(name, values, prefix))
>
>      def visit_array_type(self, name, info, element_type):
>          if isinstance(element_type, QAPISchemaBuiltinType):
> @@ -215,20 +220,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>              self._btin += gen_array(name, element_type)
>              self._btin += gen_type_cleanup_decl(name)
>              if self._opt_builtins:
> -                self.defn += gen_type_cleanup(name)
> +                self._genc.add(gen_type_cleanup(name))
>          else:
> -            self._fwdecl += gen_fwd_object_or_array(name)
> -            self.decl += gen_array(name, element_type)
> +            self._genh.preamble_add(gen_fwd_object_or_array(name))
> +            self._genh.add(gen_array(name, element_type))
>              self._gen_type_cleanup(name)
>
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self._fwdecl += gen_fwd_object_or_array(name)
> -        self.decl += gen_object(name, base, members, variants)
> +        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_object(name, base, members, variants))
>          if base and not base.is_implicit():
> -            self.decl += gen_upcast(name, base)
> +            self._genh.add(gen_upcast(name, base))
>          # TODO Worth changing the visitor signature, so we could
>          # directly use rather than repeat type.is_implicit()?
>          if not name.startswith('q_'):
> @@ -236,31 +241,13 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>              self._gen_type_cleanup(name)
>
>      def visit_alternate_type(self, name, info, variants):
> -        self._fwdecl += gen_fwd_object_or_array(name)
> -        self.decl += gen_object(name, None, [variants.tag_member], variants)
> +        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_object(name, None,
> +                                  [variants.tag_member], variants))
>          self._gen_type_cleanup(name)
>
>
>  def gen_types(schema, output_dir, prefix, opt_builtins):
> -    blurb = ' * Schema-defined QAPI types'
> -    genc = QAPIGenC(blurb, __doc__)
> -    genh = QAPIGenH(blurb, __doc__)
> -
> -    genc.add(mcgen('''
> -#include "qemu/osdep.h"
> -#include "qapi/dealloc-visitor.h"
> -#include "%(prefix)sqapi-types.h"
> -#include "%(prefix)sqapi-visit.h"
> -''',
> -                   prefix=prefix))
> -
> -    genh.add(mcgen('''
> -#include "qapi/util.h"
> -'''))
> -
> -    vis = QAPISchemaGenTypeVisitor(opt_builtins)
> +    vis = QAPISchemaGenTypeVisitor(prefix, opt_builtins)
>      schema.visit(vis)
> -    genc.add(vis.defn)
> -    genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qapi-types.c')
> -    genh.write(output_dir, prefix + 'qapi-types.h')
> +    vis.write(output_dir)
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index f966e7975f..3d09d44265 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -263,16 +263,27 @@ out:
>                   c_name=c_name(name))
>
>
> -class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> -    def __init__(self, opt_builtins):
> +class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
> +
> +    def __init__(self, prefix, opt_builtins):
> +        QAPISchemaMonolithicCVisitor.__init__(
> +            self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
> +            __doc__)
>          self._opt_builtins = opt_builtins
> -        self.decl = None
> -        self.defn = None
> -        self._btin = None
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
> +#include "%(prefix)sqapi-visit.h"
> +''',
> +                                      prefix=prefix))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/visitor.h"
> +#include "%(prefix)sqapi-types.h"
>
> -    def visit_begin(self, schema):
> -        self.decl = ''
> -        self.defn = ''
> +''',
> +                                      prefix=prefix))
>          self._btin = guardstart('QAPI_VISIT_BUILTIN')
>
>      def visit_end(self):
> @@ -281,7 +292,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          # simply guard them.  See also opt_builtins (command line
>          # option -b).
>          self._btin += guardend('QAPI_VISIT_BUILTIN')
> -        self.decl = self._btin + self.decl
> +        self._genh.preamble_add(self._btin)
>          self._btin = None
>
>      def visit_enum_type(self, name, info, values, prefix):
> @@ -290,10 +301,10 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          if not info:
>              self._btin += gen_visit_decl(name, scalar=True)
>              if self._opt_builtins:
> -                self.defn += gen_visit_enum(name)
> +                self._genc.add(gen_visit_enum(name))
>          else:
> -            self.decl += gen_visit_decl(name, scalar=True)
> -            self.defn += gen_visit_enum(name)
> +            self._genh.add(gen_visit_decl(name, scalar=True))
> +            self._genc.add(gen_visit_enum(name))
>
>      def visit_array_type(self, name, info, element_type):
>          decl = gen_visit_decl(name)
> @@ -301,53 +312,30 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          if isinstance(element_type, QAPISchemaBuiltinType):
>              self._btin += decl
>              if self._opt_builtins:
> -                self.defn += defn
> +                self._genc.add(defn)
>          else:
> -            self.decl += decl
> -            self.defn += defn
> +            self._genh.add(decl)
> +            self._genc.add(defn)
>
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
>          if name == 'q_empty':
>              return
> -        self.decl += gen_visit_members_decl(name)
> -        self.defn += gen_visit_object_members(name, base, members, variants)
> +        self._genh.add(gen_visit_members_decl(name))
> +        self._genc.add(gen_visit_object_members(name, base, members, variants))
>          # TODO Worth changing the visitor signature, so we could
>          # directly use rather than repeat type.is_implicit()?
>          if not name.startswith('q_'):
>              # only explicit types need an allocating visit
> -            self.decl += gen_visit_decl(name)
> -            self.defn += gen_visit_object(name, base, members, variants)
> +            self._genh.add(gen_visit_decl(name))
> +            self._genc.add(gen_visit_object(name, base, members, variants))
>
>      def visit_alternate_type(self, name, info, variants):
> -        self.decl += gen_visit_decl(name)
> -        self.defn += gen_visit_alternate(name, variants)
> +        self._genh.add(gen_visit_decl(name))
> +        self._genc.add(gen_visit_alternate(name, variants))
>
>
>  def gen_visit(schema, output_dir, prefix, opt_builtins):
> -    blurb = ' * Schema-defined QAPI visitors'
> -    genc = QAPIGenC(blurb, __doc__)
> -    genh = QAPIGenH(blurb, __doc__)
> -
> -    genc.add(mcgen('''
> -#include "qemu/osdep.h"
> -#include "qemu-common.h"
> -#include "qapi/error.h"
> -#include "qapi/qmp/qerror.h"
> -#include "%(prefix)sqapi-visit.h"
> -''',
> -                   prefix=prefix))
> -
> -    genh.add(mcgen('''
> -#include "qapi/visitor.h"
> -#include "%(prefix)sqapi-types.h"
> -
> -''',
> -                   prefix=prefix))
> -
> -    vis = QAPISchemaGenVisitVisitor(opt_builtins)
> +    vis = QAPISchemaGenVisitVisitor(prefix, opt_builtins)
>      schema.visit(vis)
> -    genc.add(vis.defn)
> -    genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qapi-visit.c')
> -    genh.write(output_dir, prefix + 'qapi-visit.h')
> +    vis.write(output_dir)
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
  2018-02-12 21:44   ` Eric Blake
@ 2018-02-13 15:25   ` Marc-Andre Lureau
  2018-02-19 19:30   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:25 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

Hi

On Sun, Feb 11, 2018 at 10:35 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Linking code from multiple separate QAPI schemata into the same
> program is possible, but involves some weirdness around built-in
> types:
>
> * We generate code for built-in types into .c only with option
>   --builtins.  The user is responsible for generating code for exactly
>   one QAPI schema per program with --builtins.
>
> * We generate code for built-in types into .h regardless of
>   --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN.  Because all
>   copies of this code are exactly the same, including any combination
>   of these headers works.
>
> Replace this contraption by something more conventional: generate code
> for built-in types into their very own files: qapi-builtin-types.c,
> qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
> only with --builtins.  Obey --output-dir, but ignore --prefix for
> them.
>
> Make qapi-types.h include qapi-builtin-types.h.  With multiple
> schemata you now have multiple qapi-types.[ch], but only one
> qapi-builtin-types.[ch].  Same for qapi-visit.[ch] and
> qapi-builtin-visit.[ch].
>
> Bonus: if all you need is built-in stuff, you can include a much
> smaller header.  To be exploited shortly.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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

> ---
>  .gitignore             |  2 ++
>  Makefile               | 13 ++++++----
>  Makefile.objs          |  2 ++
>  scripts/qapi/common.py | 61 ++++++++++++++++++++++++++++++++++++++++-------
>  scripts/qapi/types.py  | 61 +++++++++++++++++++----------------------------
>  scripts/qapi/visit.py  | 64 +++++++++++++++++++++-----------------------------
>  6 files changed, 116 insertions(+), 87 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index 7d783e6e66..9477a08b6b 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -29,6 +29,8 @@
>  /qga/qapi-generated
>  /qapi-generated
>  /qapi-gen-timestamp
> +/qapi-builtin-types.[ch]
> +/qapi-builtin-visit.[ch]
>  /qapi-types.[ch]
>  /qapi-visit.[ch]
>  /qapi-event.[ch]
> diff --git a/Makefile b/Makefile
> index 164a38578e..60ddc9c945 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -90,10 +90,13 @@ endif
>  include $(SRC_PATH)/rules.mak
>
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
> -GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> -GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
> -GENERATED_FILES += qmp-introspect.h
> -GENERATED_FILES += qmp-introspect.c
> +GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
> +GENERATED_FILES += qapi-types.h qapi-types.c
> +GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
> +GENERATED_FILES += qapi-visit.h qapi-visit.c
> +GENERATED_FILES += qmp-commands.h qmp-commands.c
> +GENERATED_FILES += qapi-event.h qapi-event.c
> +GENERATED_FILES += qmp-introspect.c qmp-introspect.h
>  GENERATED_FILES += qapi-doc.texi
>
>  GENERATED_FILES += trace/generated-tcg-tracers.h
> @@ -520,7 +523,9 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/transaction.json \
>                 $(SRC_PATH)/qapi/ui.json
>
> +qapi-builtin-types.c qapi-builtin-types.h \
>  qapi-types.c qapi-types.h \
> +qapi-builtin-visit.c qapi-builtin-visit.h \
>  qapi-visit.c qapi-visit.h \
>  qmp-commands.h qmp-commands.c \
>  qapi-event.c qapi-event.h \
> diff --git a/Makefile.objs b/Makefile.objs
> index d255aaf194..2813e984fd 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -2,6 +2,8 @@
>  # Common libraries for tools and emulators
>  stub-obj-y = stubs/ crypto/
>  util-obj-y = util/ qobject/ qapi/
> +util-obj-y += qapi-builtin-types.o
> +util-obj-y += qapi-builtin-visit.o
>  util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
>
>  chardev-obj-y = chardev/
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 31d2f73e7e..de12f8469a 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1531,11 +1531,10 @@ class QAPISchema(object):
>
>      def _def_builtin_type(self, name, json_type, c_type):
>          self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
> -        # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
> -        # qapi-types.h from a single .c, all arrays of builtins must be
> -        # declared in the first file whether or not they are used.  Nicer
> -        # would be to use lazy instantiation, while figuring out how to
> -        # avoid compilation issues with multiple qapi-types.h.
> +        # Instantiating only the arrays that are actually used would
> +        # be nice, but we can't as long as their generated code
> +        # (qapi-builtin-types.[ch]) may be shared by some other
> +        # schema.
>          self._make_array_type(name, None)
>
>      def _def_predefineds(self):
> @@ -1992,14 +1991,15 @@ class QAPIGen(object):
>          return ''
>
>      def write(self, output_dir, fname):
> -        if output_dir:
> +        pathname = os.path.join(output_dir, fname)
> +        dir = os.path.dirname(pathname)
> +        if dir:
>              try:
> -                os.makedirs(output_dir)
> +                os.makedirs(dir)
>              except os.error as e:
>                  if e.errno != errno.EEXIST:
>                      raise
> -        fd = os.open(os.path.join(output_dir, fname),
> -                     os.O_RDWR | os.O_CREAT, 0666)
> +        fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0666)
>          f = os.fdopen(fd, 'r+')
>          text = (self._top(fname) + self._preamble + self._body
>                  + self._bottom(fname))
> @@ -2046,6 +2046,7 @@ class QAPIGenH(QAPIGenC):
>
>
>  class QAPIGenDoc(QAPIGen):
> +
>      def _top(self, fname):
>          return (QAPIGen._top(self, fname)
>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
> @@ -2062,3 +2063,45 @@ class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
>      def write(self, output_dir):
>          self._genc.write(output_dir, self._prefix + self._what + '.c')
>          self._genh.write(output_dir, self._prefix + self._what + '.h')
> +
> +
> +class QAPISchemaModularCVisitor(QAPISchemaVisitor):
> +
> +    def __init__(self, prefix, what, blurb, pydoc):
> +        self._prefix = prefix
> +        self._what = what
> +        self._blurb = blurb
> +        self._pydoc = pydoc
> +        self._module = {}
> +
> +    def _module_basename(self, what, name):
> +        if name is None:
> +            return re.sub(r'-', '-builtin-', what)
> +        return self._prefix + what
> +
> +    def _add_module(self, name, blurb):
> +        genc = QAPIGenC(blurb, self._pydoc)
> +        genh = QAPIGenH(blurb, self._pydoc)
> +        self._module[name] = (genc, genh)
> +        self._set_module(name)
> +
> +    def _set_module(self, name):
> +        self._genc, self._genh = self._module[name]
> +
> +    def write(self, output_dir, opt_builtins):
> +        for name in self._module:
> +            if name is None and not opt_builtins:
> +                continue
> +            basename = self._module_basename(self._what, name)
> +            (genc, genh) = self._module[name]
> +            genc.write(output_dir, basename + '.c')
> +            genh.write(output_dir, basename + '.h')
> +
> +    def _begin_module(self, name):
> +        pass
> +
> +    def visit_module(self, name):
> +        if len(self._module) != 1:
> +            return
> +        self._add_module(name, self._blurb)
> +        self._begin_module(name)
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index d2b8423479..59826b1162 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -167,64 +167,51 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
>      return ret
>
>
> -class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
> +class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>
> -    def __init__(self, prefix, opt_builtins):
> -        QAPISchemaMonolithicCVisitor.__init__(
> +    def __init__(self, prefix):
> +        QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
>              __doc__)
> -        self._opt_builtins = opt_builtins
> +        self._add_module(None, ' * Built-in QAPI types')
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qapi/dealloc-visitor.h"
> +#include "qapi-builtin-types.h"
> +#include "qapi-builtin-visit.h"
> +'''))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/util.h"
> +'''))
> +
> +    def _begin_module(self, name):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
>  #include "%(prefix)sqapi-types.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -                                      prefix=prefix))
> +                                      prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi/util.h"
> +#include "qapi-builtin-types.h"
>  '''))
> -        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
>
>      def visit_begin(self, schema):
>          # gen_object() is recursive, ensure it doesn't visit the empty type
>          objects_seen.add(schema.the_empty_object_type.name)
>
> -    def visit_end(self):
> -        # To avoid header dependency hell, we always generate
> -        # declarations for built-in types in our header files and
> -        # simply guard them.  See also opt_builtins (command line
> -        # option -b).
> -        self._btin += guardend('QAPI_TYPES_BUILTIN')
> -        self._genh.preamble_add(self._btin)
> -        self._btin = None
> -
>      def _gen_type_cleanup(self, name):
>          self._genh.add(gen_type_cleanup_decl(name))
>          self._genc.add(gen_type_cleanup(name))
>
>      def visit_enum_type(self, name, info, values, prefix):
> -        # Special case for our lone builtin enum type
> -        # TODO use something cleaner than existence of info
> -        if not info:
> -            self._btin += gen_enum(name, values, prefix)
> -            if self._opt_builtins:
> -                self._genc.add(gen_enum_lookup(name, values, prefix))
> -        else:
> -            self._genh.preamble_add(gen_enum(name, values, prefix))
> -            self._genc.add(gen_enum_lookup(name, values, prefix))
> +        self._genh.preamble_add(gen_enum(name, values, prefix))
> +        self._genc.add(gen_enum_lookup(name, values, prefix))
>
>      def visit_array_type(self, name, info, element_type):
> -        if isinstance(element_type, QAPISchemaBuiltinType):
> -            self._btin += gen_fwd_object_or_array(name)
> -            self._btin += gen_array(name, element_type)
> -            self._btin += gen_type_cleanup_decl(name)
> -            if self._opt_builtins:
> -                self._genc.add(gen_type_cleanup(name))
> -        else:
> -            self._genh.preamble_add(gen_fwd_object_or_array(name))
> -            self._genh.add(gen_array(name, element_type))
> -            self._gen_type_cleanup(name)
> +        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_array(name, element_type))
> +        self._gen_type_cleanup(name)
>
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
> @@ -248,6 +235,6 @@ class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
>
>
>  def gen_types(schema, output_dir, prefix, opt_builtins):
> -    vis = QAPISchemaGenTypeVisitor(prefix, opt_builtins)
> +    vis = QAPISchemaGenTypeVisitor(prefix)
>      schema.visit(vis)
> -    vis.write(output_dir)
> +    vis.write(output_dir, opt_builtins)
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 3d09d44265..9b678e7263 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -263,13 +263,27 @@ out:
>                   c_name=c_name(name))
>
>
> -class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
> +class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>
> -    def __init__(self, prefix, opt_builtins):
> -        QAPISchemaMonolithicCVisitor.__init__(
> +    def __init__(self, prefix):
> +        QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
>              __doc__)
> -        self._opt_builtins = opt_builtins
> +        self._add_module(None, ' * Built-in QAPI visitors')
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qapi/error.h"
> +#include "qapi-builtin-visit.h"
> +'''))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/visitor.h"
> +#include "qapi-builtin-types.h"
> +
> +''',
> +                                      prefix=prefix))
> +
> +    def _begin_module(self, name):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> @@ -277,45 +291,21 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
>  #include "qapi/qmp/qerror.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -                                      prefix=prefix))
> +                                      prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi/visitor.h"
> +#include "qapi-builtin-visit.h"
>  #include "%(prefix)sqapi-types.h"
>
>  ''',
> -                                      prefix=prefix))
> -        self._btin = guardstart('QAPI_VISIT_BUILTIN')
> -
> -    def visit_end(self):
> -        # To avoid header dependency hell, we always generate
> -        # declarations for built-in types in our header files and
> -        # simply guard them.  See also opt_builtins (command line
> -        # option -b).
> -        self._btin += guardend('QAPI_VISIT_BUILTIN')
> -        self._genh.preamble_add(self._btin)
> -        self._btin = None
> +                                      prefix=self._prefix))
>
>      def visit_enum_type(self, name, info, values, prefix):
> -        # Special case for our lone builtin enum type
> -        # TODO use something cleaner than existence of info
> -        if not info:
> -            self._btin += gen_visit_decl(name, scalar=True)
> -            if self._opt_builtins:
> -                self._genc.add(gen_visit_enum(name))
> -        else:
> -            self._genh.add(gen_visit_decl(name, scalar=True))
> -            self._genc.add(gen_visit_enum(name))
> +        self._genh.add(gen_visit_decl(name, scalar=True))
> +        self._genc.add(gen_visit_enum(name))
>
>      def visit_array_type(self, name, info, element_type):
> -        decl = gen_visit_decl(name)
> -        defn = gen_visit_list(name, element_type)
> -        if isinstance(element_type, QAPISchemaBuiltinType):
> -            self._btin += decl
> -            if self._opt_builtins:
> -                self._genc.add(defn)
> -        else:
> -            self._genh.add(decl)
> -            self._genc.add(defn)
> +        self._genh.add(gen_visit_decl(name))
> +        self._genc.add(gen_visit_list(name, element_type))
>
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
> @@ -336,6 +326,6 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
>
>
>  def gen_visit(schema, output_dir, prefix, opt_builtins):
> -    vis = QAPISchemaGenVisitVisitor(prefix, opt_builtins)
> +    vis = QAPISchemaGenVisitVisitor(prefix)
>      schema.visit(vis)
> -    vis.write(output_dir)
> +    vis.write(output_dir, opt_builtins)
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
  2018-02-12 22:13   ` Eric Blake
@ 2018-02-13 15:54   ` Marc-Andre Lureau
  1 sibling, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 15:54 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> In my "build everything" tree, a change to the types in
> qapi-schema.json triggers a recompile of about 4800 out of 5100
> objects.
>
> The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h,
> qapi-types.h.  Each of these headers still includes all its shards.
> Reduce compile time by including just the shards we actually need.
>
> To illustrate the benefits: adding a type to qapi/migration.json now
> recompiles some 2300 instead of 4800 objects.  The next commit will
> improve it further.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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


> ---
>  backends/cryptodev.c             |  1 -
>  backends/hostmem.c               |  3 ++-
>  block.c                          |  1 -
>  block/block-backend.c            |  2 +-
>  block/crypto.c                   |  2 +-
>  block/nbd.c                      |  2 +-
>  block/nfs.c                      |  2 +-
>  block/qapi.c                     |  4 ++--
>  block/qcow2.c                    |  3 +--
>  block/quorum.c                   |  2 +-
>  block/sheepdog.c                 |  2 +-
>  block/ssh.c                      |  2 +-
>  block/throttle-groups.c          |  2 +-
>  block/write-threshold.c          |  4 ++--
>  blockdev-nbd.c                   |  2 +-
>  blockdev.c                       |  5 +++--
>  blockjob.c                       |  2 +-
>  chardev/char-fe.c                |  1 -
>  chardev/char-ringbuf.c           |  2 +-
>  chardev/char-socket.c            |  1 +
>  chardev/char.c                   |  3 +--
>  cpus.c                           |  2 +-
>  crypto/cipherpriv.h              |  2 +-
>  hmp.c                            |  2 +-
>  hw/acpi/core.c                   |  2 +-
>  hw/block/block.c                 |  1 +
>  hw/block/hd-geometry.c           |  1 +
>  hw/char/virtio-console.c         |  2 +-
>  hw/core/machine.c                |  2 +-
>  hw/i386/pc.c                     |  2 +-
>  hw/mem/nvdimm.c                  |  1 -
>  hw/net/rocker/qmp-norocker.c     |  2 +-
>  hw/net/rocker/rocker.c           |  2 +-
>  hw/net/rocker/rocker_fp.c        |  2 +-
>  hw/net/rocker/rocker_of_dpa.c    |  2 +-
>  hw/net/virtio-net.c              |  2 +-
>  hw/ppc/spapr_rtas.c              |  1 -
>  hw/tpm/tpm_emulator.c            |  1 +
>  hw/tpm/tpm_passthrough.c         |  1 +
>  hw/watchdog/watchdog.c           |  2 +-
>  include/block/block.h            |  2 +-
>  include/block/dirty-bitmap.h     |  2 +-
>  include/block/nbd.h              |  2 +-
>  include/chardev/char.h           |  1 +
>  include/crypto/cipher.h          |  2 +-
>  include/crypto/hash.h            |  2 +-
>  include/crypto/hmac.h            |  2 +-
>  include/crypto/secret.h          |  1 +
>  include/crypto/tlscreds.h        |  1 +
>  include/hw/block/block.h         |  2 +-
>  include/hw/block/fdc.h           |  2 +-
>  include/hw/ppc/spapr_drc.h       |  1 +
>  include/hw/qdev-properties.h     |  1 +
>  include/io/dns-resolver.h        |  1 +
>  include/migration/colo.h         |  2 +-
>  include/migration/failover.h     |  2 +-
>  include/migration/global_state.h |  1 +
>  include/monitor/monitor.h        |  1 +
>  include/net/filter.h             |  1 +
>  include/net/net.h                |  2 +-
>  include/qapi/clone-visitor.h     |  1 -
>  include/qapi/error.h             |  2 +-
>  include/qapi/qmp/qobject.h       |  2 +-
>  include/qapi/visitor.h           |  2 +-
>  include/qemu/sockets.h           |  2 +-
>  include/qemu/throttle.h          |  2 +-
>  include/qom/cpu.h                |  1 +
>  include/qom/object.h             |  2 +-
>  include/sysemu/dump.h            |  2 ++
>  include/sysemu/hostmem.h         |  1 +
>  include/sysemu/replay.h          |  1 +
>  include/sysemu/sysemu.h          |  1 +
>  include/sysemu/tpm.h             |  1 +
>  include/sysemu/watchdog.h        |  2 +-
>  include/ui/input.h               |  2 +-
>  io/channel-socket.c              |  1 +
>  io/dns-resolver.c                |  1 +
>  migration/colo-failover.c        |  2 +-
>  migration/colo.c                 |  2 +-
>  migration/migration.c            |  4 ++--
>  migration/migration.h            |  1 +
>  migration/ram.c                  |  2 +-
>  migration/ram.h                  |  2 +-
>  net/colo-compare.c               |  1 -
>  net/filter-buffer.c              |  2 +-
>  net/filter-mirror.c              |  1 -
>  net/filter-rewriter.c            |  1 -
>  net/net.c                        |  4 ++--
>  net/tap_int.h                    |  2 +-
>  net/vhost-user.c                 |  2 +-
>  qemu-img.c                       |  2 +-
>  qom/object.c                     |  2 +-
>  qom/object_interfaces.c          |  1 -
>  replay/replay-input.c            |  1 +
>  replication.h                    |  1 +
>  scripts/qapi/commands.py         | 14 ++++++++------
>  scripts/qapi/events.py           | 10 ++++++----
>  scripts/qapi/types.py            |  8 +++++---
>  scripts/qapi/visit.py            | 10 ++++++----
>  stubs/tpm.c                      |  3 ++-
>  target/s390x/kvm.c               |  1 -
>  tests/test-char.c                |  2 +-
>  tests/test-qmp-event.c           |  1 -
>  tpm.c                            |  2 +-
>  trace/qmp.c                      |  2 +-
>  ui/console.c                     |  2 +-
>  ui/input-legacy.c                |  2 +-
>  ui/input.c                       |  2 +-
>  ui/spice-core.c                  |  4 ++--
>  ui/vnc.c                         |  2 +-
>  ui/vnc.h                         |  1 +
>  util/qemu-sockets.c              |  2 +-
>  vl.c                             |  4 ++--
>  113 files changed, 133 insertions(+), 109 deletions(-)
>
> diff --git a/backends/cryptodev.c b/backends/cryptodev.c
> index d0dff1a463..f35be377ef 100644
> --- a/backends/cryptodev.c
> +++ b/backends/cryptodev.c
> @@ -26,7 +26,6 @@
>  #include "hw/boards.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>  #include "qemu/config-file.h"
>  #include "qom/object_interfaces.h"
>  #include "hw/virtio/virtio-crypto.h"
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 81d14554a7..0afaf7160a 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -9,12 +9,13 @@
>   * This work is licensed under the terms of the GNU GPL, version 2 or later.
>   * See the COPYING file in the top-level directory.
>   */
> +
>  #include "qemu/osdep.h"
>  #include "sysemu/hostmem.h"
>  #include "hw/boards.h"
>  #include "qapi/error.h"
> +#include "qapi-builtin-visit.h"
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>  #include "qemu/config-file.h"
>  #include "qom/object_interfaces.h"
>
> diff --git a/block.c b/block.c
> index 05a484b4b8..0b2784f322 100644
> --- a/block.c
> +++ b/block.c
> @@ -41,7 +41,6 @@
>  #include "qemu/coroutine.h"
>  #include "block/qapi.h"
>  #include "qemu/timer.h"
> -#include "qapi-event.h"
>  #include "qemu/cutils.h"
>  #include "qemu/id.h"
>
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 0266ac990b..94ffbb6a60 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -17,8 +17,8 @@
>  #include "block/throttle-groups.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/sysemu.h"
> -#include "qapi-event.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-block.h"
>  #include "qemu/id.h"
>  #include "qemu/option.h"
>  #include "trace.h"
> diff --git a/block/crypto.c b/block/crypto.c
> index 70e3691cd8..c87abd5250 100644
> --- a/block/crypto.c
> +++ b/block/crypto.c
> @@ -24,9 +24,9 @@
>  #include "sysemu/block-backend.h"
>  #include "crypto/block.h"
>  #include "qapi/opts-visitor.h"
> +#include "qapi/qapi-visit-crypto.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qobject-input-visitor.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
>  #include "qemu/option.h"
>  #include "block/crypto.h"
> diff --git a/block/nbd.c b/block/nbd.c
> index 411eeb42a7..6c0e766b6f 100644
> --- a/block/nbd.c
> +++ b/block/nbd.c
> @@ -33,7 +33,7 @@
>  #include "block/block_int.h"
>  #include "qemu/module.h"
>  #include "qemu/option.h"
> -#include "qapi-visit.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qapi/qobject-output-visitor.h"
>  #include "qapi/qmp/qdict.h"
> diff --git a/block/nfs.c b/block/nfs.c
> index 6576a73d6e..bbdb4fadad 100644
> --- a/block/nfs.c
> +++ b/block/nfs.c
> @@ -35,9 +35,9 @@
>  #include "qemu/uri.h"
>  #include "qemu/cutils.h"
>  #include "sysemu/sysemu.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
> -#include "qapi-visit.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qapi/qobject-output-visitor.h"
>  #include <nfsc/libnfs.h>
> diff --git a/block/qapi.c b/block/qapi.c
> index 1fdeb1ef2f..4c9923d262 100644
> --- a/block/qapi.c
> +++ b/block/qapi.c
> @@ -27,10 +27,10 @@
>  #include "block/block_int.h"
>  #include "block/throttle-groups.h"
>  #include "block/write-threshold.h"
> -#include "qmp-commands.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-block-core.h"
>  #include "qapi/qobject-output-visitor.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qlist.h"
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 9245deac19..2fc58415bb 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -30,15 +30,14 @@
>  #include "block/qcow2.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-block-core.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
> -#include "qapi-event.h"
>  #include "trace.h"
>  #include "qemu/option_int.h"
>  #include "qemu/cutils.h"
>  #include "qemu/bswap.h"
>  #include "qapi/opts-visitor.h"
> -#include "qapi-visit.h"
>  #include "block/crypto.h"
>
>  /*
> diff --git a/block/quorum.c b/block/quorum.c
> index 19f1c34425..14333c18aa 100644
> --- a/block/quorum.c
> +++ b/block/quorum.c
> @@ -18,11 +18,11 @@
>  #include "qemu/option.h"
>  #include "block/block_int.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-block.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qlist.h"
>  #include "qapi/qmp/qstring.h"
> -#include "qapi-event.h"
>  #include "crypto/hash.h"
>
>  #define HASH_LENGTH 32
> diff --git a/block/sheepdog.c b/block/sheepdog.c
> index af125a2c8d..4c20fcda04 100644
> --- a/block/sheepdog.c
> +++ b/block/sheepdog.c
> @@ -13,8 +13,8 @@
>   */
>
>  #include "qemu/osdep.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qemu/uri.h"
> diff --git a/block/ssh.c b/block/ssh.c
> index b63addcf94..b11d4c5e86 100644
> --- a/block/ssh.c
> +++ b/block/ssh.c
> @@ -34,7 +34,7 @@
>  #include "qemu/cutils.h"
>  #include "qemu/sockets.h"
>  #include "qemu/uri.h"
> -#include "qapi-visit.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qobject-input-visitor.h"
> diff --git a/block/throttle-groups.c b/block/throttle-groups.c
> index f26bcb5eee..36cc0430c3 100644
> --- a/block/throttle-groups.c
> +++ b/block/throttle-groups.c
> @@ -30,7 +30,7 @@
>  #include "qemu/thread.h"
>  #include "sysemu/qtest.h"
>  #include "qapi/error.h"
> -#include "qapi-visit.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qom/object.h"
>  #include "qom/object_interfaces.h"
>
> diff --git a/block/write-threshold.c b/block/write-threshold.c
> index db3de0fa6d..1d48fc2077 100644
> --- a/block/write-threshold.c
> +++ b/block/write-threshold.c
> @@ -15,9 +15,9 @@
>  #include "qemu/coroutine.h"
>  #include "block/write-threshold.h"
>  #include "qemu/notify.h"
> -#include "qapi-event.h"
>  #include "qapi/error.h"
> -#include "qmp-commands.h"
> +#include "qapi/qapi-commands-block-core.h"
> +#include "qapi/qapi-events-block-core.h"
>
>  uint64_t bdrv_write_threshold_get(const BlockDriverState *bs)
>  {
> diff --git a/blockdev-nbd.c b/blockdev-nbd.c
> index 3a5479bdad..65a84739ed 100644
> --- a/blockdev-nbd.c
> +++ b/blockdev-nbd.c
> @@ -14,8 +14,8 @@
>  #include "sysemu/block-backend.h"
>  #include "hw/block/block.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-block.h"
>  #include "sysemu/sysemu.h"
> -#include "qmp-commands.h"
>  #include "block/nbd.h"
>  #include "io/channel-socket.h"
>  #include "io/net-listener.h"
> diff --git a/blockdev.c b/blockdev.c
> index bdbdeae7e4..85e011191b 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -40,10 +40,12 @@
>  #include "qemu/error-report.h"
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
> +#include "qapi/qapi-commands-block.h"
> +#include "qapi/qapi-commands-transaction.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qlist.h"
> @@ -51,7 +53,6 @@
>  #include "sysemu/sysemu.h"
>  #include "sysemu/iothread.h"
>  #include "block/block_int.h"
> -#include "qmp-commands.h"
>  #include "block/trace.h"
>  #include "sysemu/arch_init.h"
>  #include "sysemu/qtest.h"
> diff --git a/blockjob.c b/blockjob.c
> index 3f52f29f75..801d29d849 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -30,11 +30,11 @@
>  #include "block/block_int.h"
>  #include "sysemu/block-backend.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-block-core.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/coroutine.h"
>  #include "qemu/id.h"
>  #include "qemu/timer.h"
> -#include "qapi-event.h"
>
>  /* Right now, this mutex is only needed to synchronize accesses to job->busy
>   * and job->sleep_timer, such as concurrent calls to block_job_do_yield and
> diff --git a/chardev/char-fe.c b/chardev/char-fe.c
> index e5f870e4d2..392db78b13 100644
> --- a/chardev/char-fe.c
> +++ b/chardev/char-fe.c
> @@ -25,7 +25,6 @@
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
> -#include "qapi-visit.h"
>  #include "sysemu/replay.h"
>
>  #include "chardev/char-fe.h"
> diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
> index 679afaa4fd..87832e2792 100644
> --- a/chardev/char-ringbuf.c
> +++ b/chardev/char-ringbuf.c
> @@ -24,8 +24,8 @@
>
>  #include "qemu/osdep.h"
>  #include "chardev/char.h"
> -#include "qmp-commands.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-char.h"
>  #include "qemu/base64.h"
>  #include "qemu/option.h"
>
> diff --git a/chardev/char-socket.c b/chardev/char-socket.c
> index bdd6cff5f6..22f65971a1 100644
> --- a/chardev/char-socket.c
> +++ b/chardev/char-socket.c
> @@ -31,6 +31,7 @@
>  #include "qemu/option.h"
>  #include "qapi/error.h"
>  #include "qapi/clone-visitor.h"
> +#include "qapi/qapi-visit-sockets.h"
>
>  #include "chardev/char-io.h"
>
> diff --git a/chardev/char.c b/chardev/char.c
> index c9a4da5516..5d7b079ef0 100644
> --- a/chardev/char.c
> +++ b/chardev/char.c
> @@ -29,9 +29,8 @@
>  #include "qemu/config-file.h"
>  #include "qemu/error-report.h"
>  #include "chardev/char.h"
> -#include "qmp-commands.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-char.h"
>  #include "qapi/qmp/qerror.h"
>  #include "sysemu/replay.h"
>  #include "qemu/help_option.h"
> diff --git a/cpus.c b/cpus.c
> index f298b659f4..ddb7f9b811 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -27,6 +27,7 @@
>  #include "cpu.h"
>  #include "monitor/monitor.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-run-state.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/error-report.h"
>  #include "sysemu/sysemu.h"
> @@ -49,7 +50,6 @@
>  #include "qemu/bitmap.h"
>  #include "qemu/seqlock.h"
>  #include "tcg.h"
> -#include "qapi-event.h"
>  #include "hw/nmi.h"
>  #include "sysemu/replay.h"
>  #include "hw/boards.h"
> diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h
> index 77da4c2f32..0823239f41 100644
> --- a/crypto/cipherpriv.h
> +++ b/crypto/cipherpriv.h
> @@ -15,7 +15,7 @@
>  #ifndef QCRYPTO_CIPHERPRIV_H
>  #define QCRYPTO_CIPHERPRIV_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-crypto.h"
>
>  typedef struct QCryptoCipherDriver QCryptoCipherDriver;
>
> diff --git a/hmp.c b/hmp.c
> index 7870d6a300..a49f4c126e 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -29,11 +29,11 @@
>  #include "monitor/qdev.h"
>  #include "qapi/error.h"
>  #include "qapi/opts-visitor.h"
> +#include "qapi-builtin-visit.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/string-output-visitor.h"
> -#include "qapi-visit.h"
>  #include "qom/object_interfaces.h"
>  #include "ui/console.h"
>  #include "block/nbd.h"
> diff --git a/hw/acpi/core.c b/hw/acpi/core.c
> index b50b3ca772..5d4ce925dc 100644
> --- a/hw/acpi/core.c
> +++ b/hw/acpi/core.c
> @@ -27,8 +27,8 @@
>  #include "qemu/config-file.h"
>  #include "qapi/error.h"
>  #include "qapi/opts-visitor.h"
> +#include "qapi/qapi-events-run-state.h"
>  #include "qapi-visit.h"
> -#include "qapi-event.h"
>  #include "qemu/error-report.h"
>  #include "qemu/option.h"
>
> diff --git a/hw/block/block.c b/hw/block/block.c
> index b0269c857f..b91e2b6d7e 100644
> --- a/hw/block/block.c
> +++ b/hw/block/block.c
> @@ -12,6 +12,7 @@
>  #include "sysemu/block-backend.h"
>  #include "hw/block/block.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-types-block.h"
>  #include "qemu/error-report.h"
>
>  void blkconf_serial(BlockConf *conf, char **serial)
> diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
> index 57ad5012a7..79384a2b0a 100644
> --- a/hw/block/hd-geometry.c
> +++ b/hw/block/hd-geometry.c
> @@ -32,6 +32,7 @@
>
>  #include "qemu/osdep.h"
>  #include "sysemu/block-backend.h"
> +#include "qapi/qapi-types-block.h"
>  #include "qemu/bswap.h"
>  #include "hw/block/block.h"
>  #include "trace.h"
> diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
> index 4be5d4ee52..679a824888 100644
> --- a/hw/char/virtio-console.c
> +++ b/hw/char/virtio-console.c
> @@ -15,8 +15,8 @@
>  #include "qemu/error-report.h"
>  #include "trace.h"
>  #include "hw/virtio/virtio-serial.h"
> -#include "qapi-event.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-char.h"
>
>  #define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
>  #define VIRTIO_CONSOLE(obj) \
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index cdc1163dc6..f35075bff6 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -13,7 +13,7 @@
>  #include "qemu/osdep.h"
>  #include "hw/boards.h"
>  #include "qapi/error.h"
> -#include "qapi-visit.h"
> +#include "qapi/qapi-visit-common.h"
>  #include "qapi/visitor.h"
>  #include "hw/sysbus.h"
>  #include "sysemu/sysemu.h"
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 55e69d66fe..94cfd40ef2 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -67,8 +67,8 @@
>  #include "acpi-build.h"
>  #include "hw/mem/pc-dimm.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-common.h"
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>  #include "qom/cpu.h"
>  #include "hw/nmi.h"
>  #include "hw/i386/intel_iommu.h"
> diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
> index 61e677f92f..acb656b672 100644
> --- a/hw/mem/nvdimm.c
> +++ b/hw/mem/nvdimm.c
> @@ -25,7 +25,6 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>  #include "hw/mem/nvdimm.h"
>
>  static void nvdimm_get_label_size(Object *obj, Visitor *v, const char *name,
> diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c
> index 94c1e480ae..0d60513c01 100644
> --- a/hw/net/rocker/qmp-norocker.c
> +++ b/hw/net/rocker/qmp-norocker.c
> @@ -17,8 +17,8 @@
>
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> -#include "qmp-commands.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-rocker.h"
>  #include "qapi/qmp/qerror.h"
>
>  RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
> diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
> index a2a76c2a74..c02cbefece 100644
> --- a/hw/net/rocker/rocker.c
> +++ b/hw/net/rocker/rocker.c
> @@ -22,9 +22,9 @@
>  #include "net/net.h"
>  #include "net/eth.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-rocker.h"
>  #include "qemu/iov.h"
>  #include "qemu/bitops.h"
> -#include "qmp-commands.h"
>
>  #include "rocker.h"
>  #include "rocker_hw.h"
> diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
> index 4b3c9847db..27b17c890f 100644
> --- a/hw/net/rocker/rocker_fp.c
> +++ b/hw/net/rocker/rocker_fp.c
> @@ -16,7 +16,7 @@
>
>  #include "qemu/osdep.h"
>  #include "net/clients.h"
> -
> +#include "qapi/qapi-types-rocker.h"
>  #include "rocker.h"
>  #include "rocker_hw.h"
>  #include "rocker_fp.h"
> diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
> index 9339df2d09..60046720a5 100644
> --- a/hw/net/rocker/rocker_of_dpa.c
> +++ b/hw/net/rocker/rocker_of_dpa.c
> @@ -17,9 +17,9 @@
>  #include "qemu/osdep.h"
>  #include "net/eth.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-rocker.h"
>  #include "qemu/iov.h"
>  #include "qemu/timer.h"
> -#include "qmp-commands.h"
>
>  #include "rocker.h"
>  #include "rocker_hw.h"
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 369d40b378..188744e17d 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -23,7 +23,7 @@
>  #include "net/vhost_net.h"
>  #include "hw/virtio/virtio-bus.h"
>  #include "qapi/error.h"
> -#include "qapi-event.h"
> +#include "qapi/qapi-events-net.h"
>  #include "hw/virtio/virtio-access.h"
>  #include "migration/misc.h"
>
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index 4bb939d3d1..0ec5fa4cfe 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -38,7 +38,6 @@
>  #include "hw/ppc/spapr_vio.h"
>  #include "hw/ppc/spapr_rtas.h"
>  #include "hw/ppc/ppc.h"
> -#include "qapi-event.h"
>  #include "hw/boards.h"
>
>  #include <libfdt.h>
> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
> index b787aee13b..f187a72c10 100644
> --- a/hw/tpm/tpm_emulator.c
> +++ b/hw/tpm/tpm_emulator.c
> @@ -38,6 +38,7 @@
>  #include "migration/blocker.h"
>  #include "qapi/error.h"
>  #include "qapi/clone-visitor.h"
> +#include "qapi/qapi-visit-tpm.h"
>  #include "chardev/char-fe.h"
>
>  #define DEBUG_TPM 0
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index a495fe07f4..211df3191c 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -30,6 +30,7 @@
>  #include "tpm_int.h"
>  #include "hw/hw.h"
>  #include "qapi/clone-visitor.h"
> +#include "qapi/qapi-visit-tpm.h"
>  #include "tpm_util.h"
>
>  #define DEBUG_TPM 0
> diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
> index 98a5dd6689..c7843d5748 100644
> --- a/hw/watchdog/watchdog.c
> +++ b/hw/watchdog/watchdog.c
> @@ -24,9 +24,9 @@
>  #include "qemu/config-file.h"
>  #include "qemu/queue.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-run-state.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/watchdog.h"
> -#include "qapi-event.h"
>  #include "hw/nmi.h"
>  #include "qemu/help_option.h"
>  #include "qmp-commands.h"
> diff --git a/include/block/block.h b/include/block/block.h
> index 24ef816960..a1936996db 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -2,7 +2,7 @@
>  #define BLOCK_H
>
>  #include "block/aio.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-block-core.h"
>  #include "qemu/iov.h"
>  #include "qemu/coroutine.h"
>  #include "block/accounting.h"
> diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
> index 3da8486ab1..1454be358d 100644
> --- a/include/block/dirty-bitmap.h
> +++ b/include/block/dirty-bitmap.h
> @@ -2,7 +2,7 @@
>  #define BLOCK_DIRTY_BITMAP_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-block-core.h"
>  #include "qemu/hbitmap.h"
>
>  BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
> diff --git a/include/block/nbd.h b/include/block/nbd.h
> index fc50003003..631290dac9 100644
> --- a/include/block/nbd.h
> +++ b/include/block/nbd.h
> @@ -20,7 +20,7 @@
>  #ifndef NBD_H
>  #define NBD_H
>
> -
> +#include "qapi/qapi-types-block.h"
>  #include "io/channel-socket.h"
>  #include "crypto/tlscreds.h"
>
> diff --git a/include/chardev/char.h b/include/chardev/char.h
> index a381dc3df8..ebf1e0ba04 100644
> --- a/include/chardev/char.h
> +++ b/include/chardev/char.h
> @@ -1,6 +1,7 @@
>  #ifndef QEMU_CHAR_H
>  #define QEMU_CHAR_H
>
> +#include "qapi/qapi-types-char.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/bitmap.h"
>  #include "qom/object.h"
> diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h
> index 984fb8243f..bce2d4c8e4 100644
> --- a/include/crypto/cipher.h
> +++ b/include/crypto/cipher.h
> @@ -21,7 +21,7 @@
>  #ifndef QCRYPTO_CIPHER_H
>  #define QCRYPTO_CIPHER_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-crypto.h"
>
>  typedef struct QCryptoCipher QCryptoCipher;
>
> diff --git a/include/crypto/hash.h b/include/crypto/hash.h
> index ca3267f3df..077ac7bea0 100644
> --- a/include/crypto/hash.h
> +++ b/include/crypto/hash.h
> @@ -21,7 +21,7 @@
>  #ifndef QCRYPTO_HASH_H
>  #define QCRYPTO_HASH_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-crypto.h"
>
>  /* See also "QCryptoHashAlgorithm" defined in qapi/crypto.json */
>
> diff --git a/include/crypto/hmac.h b/include/crypto/hmac.h
> index 5e88905989..aa3c97a2ff 100644
> --- a/include/crypto/hmac.h
> +++ b/include/crypto/hmac.h
> @@ -12,7 +12,7 @@
>  #ifndef QCRYPTO_HMAC_H
>  #define QCRYPTO_HMAC_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-crypto.h"
>
>  typedef struct QCryptoHmac QCryptoHmac;
>  struct QCryptoHmac {
> diff --git a/include/crypto/secret.h b/include/crypto/secret.h
> index 07a963e794..edd0e13236 100644
> --- a/include/crypto/secret.h
> +++ b/include/crypto/secret.h
> @@ -21,6 +21,7 @@
>  #ifndef QCRYPTO_SECRET_H
>  #define QCRYPTO_SECRET_H
>
> +#include "qapi/qapi-types-crypto.h"
>  #include "qom/object.h"
>
>  #define TYPE_QCRYPTO_SECRET "secret"
> diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h
> index ad47d88be7..6b011e1dbc 100644
> --- a/include/crypto/tlscreds.h
> +++ b/include/crypto/tlscreds.h
> @@ -21,6 +21,7 @@
>  #ifndef QCRYPTO_TLSCREDS_H
>  #define QCRYPTO_TLSCREDS_H
>
> +#include "qapi/qapi-types-crypto.h"
>  #include "qom/object.h"
>
>  #ifdef CONFIG_GNUTLS
> diff --git a/include/hw/block/block.h b/include/hw/block/block.h
> index f532d10e35..d4f4dfffab 100644
> --- a/include/hw/block/block.h
> +++ b/include/hw/block/block.h
> @@ -12,7 +12,7 @@
>  #define HW_BLOCK_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-block-core.h"
>
>  /* Configuration */
>
> diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
> index 68a0c904ea..3b813c7f7d 100644
> --- a/include/hw/block/fdc.h
> +++ b/include/hw/block/fdc.h
> @@ -2,7 +2,7 @@
>  #define HW_FDC_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-block.h"
>
>  /* fdc.c */
>  #define MAX_FD 2
> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
> index f8d9f5b231..f6ff32e7e2 100644
> --- a/include/hw/ppc/spapr_drc.h
> +++ b/include/hw/ppc/spapr_drc.h
> @@ -14,6 +14,7 @@
>  #define HW_SPAPR_DRC_H
>
>  #include <libfdt.h>
> +#include "qapi/qapi-types-run-state.h"
>  #include "qom/object.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/qdev.h"
> diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
> index 1d61a35108..40c2c8acb1 100644
> --- a/include/hw/qdev-properties.h
> +++ b/include/hw/qdev-properties.h
> @@ -1,6 +1,7 @@
>  #ifndef QEMU_QDEV_PROPERTIES_H
>  #define QEMU_QDEV_PROPERTIES_H
>
> +#include "qapi-types.h"
>  #include "hw/qdev-core.h"
>
>  /*** qdev-properties.c ***/
> diff --git a/include/io/dns-resolver.h b/include/io/dns-resolver.h
> index 2f69c08c13..1a162185cc 100644
> --- a/include/io/dns-resolver.h
> +++ b/include/io/dns-resolver.h
> @@ -22,6 +22,7 @@
>  #define QIO_DNS_RESOLVER_H
>
>  #include "qemu-common.h"
> +#include "qapi/qapi-types-sockets.h"
>  #include "qom/object.h"
>  #include "io/task.h"
>
> diff --git a/include/migration/colo.h b/include/migration/colo.h
> index 50ace16205..2fe48ad353 100644
> --- a/include/migration/colo.h
> +++ b/include/migration/colo.h
> @@ -14,7 +14,7 @@
>  #define QEMU_COLO_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-migration.h"
>
>  void colo_info_init(void);
>
> diff --git a/include/migration/failover.h b/include/migration/failover.h
> index ad91ef2381..4c37218dcc 100644
> --- a/include/migration/failover.h
> +++ b/include/migration/failover.h
> @@ -14,7 +14,7 @@
>  #define QEMU_FAILOVER_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-migration.h"
>
>  void failover_init_state(void);
>  FailoverStatus failover_set_state(FailoverStatus old_state,
> diff --git a/include/migration/global_state.h b/include/migration/global_state.h
> index d307de8350..fd22dd3034 100644
> --- a/include/migration/global_state.h
> +++ b/include/migration/global_state.h
> @@ -13,6 +13,7 @@
>  #ifndef QEMU_MIGRATION_GLOBAL_STATE_H
>  #define QEMU_MIGRATION_GLOBAL_STATE_H
>
> +#include "qapi/qapi-types-run-state.h"
>  #include "sysemu/sysemu.h"
>
>  void register_global_state(void);
> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> index ad64ad8e68..50f7cea057 100644
> --- a/include/monitor/monitor.h
> +++ b/include/monitor/monitor.h
> @@ -3,6 +3,7 @@
>
>  #include "qemu-common.h"
>  #include "block/block.h"
> +#include "qapi-types.h"
>  #include "qemu/readline.h"
>
>  extern Monitor *cur_mon;
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 0c4a2ea6c9..435acd6f82 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -9,6 +9,7 @@
>  #ifndef QEMU_NET_FILTER_H
>  #define QEMU_NET_FILTER_H
>
> +#include "qapi/qapi-types-net.h"
>  #include "qom/object.h"
>  #include "qemu-common.h"
>  #include "net/queue.h"
> diff --git a/include/net/net.h b/include/net/net.h
> index 3fc48e4f51..727643032c 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -2,7 +2,7 @@
>  #define QEMU_NET_H
>
>  #include "qemu/queue.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-net.h"
>  #include "net/queue.h"
>  #include "migration/vmstate.h"
>
> diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h
> index b119d3daa9..5b665ee38c 100644
> --- a/include/qapi/clone-visitor.h
> +++ b/include/qapi/clone-visitor.h
> @@ -12,7 +12,6 @@
>  #define QAPI_CLONE_VISITOR_H
>
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>
>  /*
>   * The clone visitor is for direct use only by the QAPI_CLONE() macro;
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index c2115a6a4a..bcb86a79f5 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -115,7 +115,7 @@
>  #ifndef ERROR_H
>  #define ERROR_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-common.h"
>
>  /*
>   * Overall category of an error.
> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
> index 38ac68845c..a2964fbf25 100644
> --- a/include/qapi/qmp/qobject.h
> +++ b/include/qapi/qmp/qobject.h
> @@ -32,7 +32,7 @@
>  #ifndef QOBJECT_H
>  #define QOBJECT_H
>
> -#include "qapi-types.h"
> +#include "qapi-builtin-types.h"
>
>  struct QObject {
>      QType type;
> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
> index ecff296c11..9e57508446 100644
> --- a/include/qapi/visitor.h
> +++ b/include/qapi/visitor.h
> @@ -15,7 +15,7 @@
>  #ifndef QAPI_VISITOR_H
>  #define QAPI_VISITOR_H
>
> -#include "qapi-types.h"
> +#include "qapi-builtin-types.h"
>
>  /*
>   * The QAPI schema defines both a set of C data types, and a QMP wire
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 8889bcb1ec..e88d4c37ab 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -9,7 +9,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
>
>  #endif /* !_WIN32 */
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-sockets.h"
>
>  /* misc helpers */
>  int qemu_socket(int domain, int type, int protocol);
> diff --git a/include/qemu/throttle.h b/include/qemu/throttle.h
> index 03d45f44f8..abeb886d93 100644
> --- a/include/qemu/throttle.h
> +++ b/include/qemu/throttle.h
> @@ -26,7 +26,7 @@
>  #define THROTTLE_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-block-core.h"
>  #include "qemu/timer.h"
>
>  #define THROTTLE_VALUE_MAX 1000000000000000LL
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index aff88fa16f..dc6d4956a8 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -24,6 +24,7 @@
>  #include "disas/bfd.h"
>  #include "exec/hwaddr.h"
>  #include "exec/memattrs.h"
> +#include "qapi/qapi-types-run-state.h"
>  #include "qemu/bitmap.h"
>  #include "qemu/queue.h"
>  #include "qemu/thread.h"
> diff --git a/include/qom/object.h b/include/qom/object.h
> index dc73d59660..5b5c016d8f 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -14,7 +14,7 @@
>  #ifndef QEMU_OBJECT_H
>  #define QEMU_OBJECT_H
>
> -#include "qapi-types.h"
> +#include "qapi-builtin-types.h"
>  #include "qemu/queue.h"
>
>  struct TypeImpl;
> diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
> index c14bcfe8c6..2424e31425 100644
> --- a/include/sysemu/dump.h
> +++ b/include/sysemu/dump.h
> @@ -14,6 +14,8 @@
>  #ifndef DUMP_H
>  #define DUMP_H
>
> +#include "qapi-types.h"
> +
>  #define MAKEDUMPFILE_SIGNATURE      "makedumpfile"
>  #define MAX_SIZE_MDF_HEADER         (4096) /* max size of makedumpfile_header */
>  #define TYPE_FLAT_HEADER            (1)    /* type of flattened format */
> diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
> index 621a3f9d42..6424f96df9 100644
> --- a/include/sysemu/hostmem.h
> +++ b/include/sysemu/hostmem.h
> @@ -14,6 +14,7 @@
>  #define SYSEMU_HOSTMEM_H
>
>  #include "sysemu/sysemu.h" /* for MAX_NODES */
> +#include "qapi-types.h"
>  #include "qom/object.h"
>  #include "exec/memory.h"
>  #include "qemu/bitmap.h"
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index dc8ae7b6b1..fb533ed9b6 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -13,6 +13,7 @@
>   */
>
>  #include "sysemu.h"
> +#include "qapi-types.h"
>
>  /* replay clock kinds */
>  enum ReplayClockKind {
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 77bb3da582..bfbef9e69c 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -2,6 +2,7 @@
>  #define SYSEMU_H
>  /* Misc. things related to the system emulator.  */
>
> +#include "qapi/qapi-types-run-state.h"
>  #include "qemu/queue.h"
>  #include "qemu/timer.h"
>  #include "qemu/notify.h"
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index 32b753d4f3..9ae1ab6da3 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -12,6 +12,7 @@
>  #ifndef QEMU_TPM_H
>  #define QEMU_TPM_H
>
> +#include "qapi/qapi-types-tpm.h"
>  #include "qom/object.h"
>
>  int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
> diff --git a/include/sysemu/watchdog.h b/include/sysemu/watchdog.h
> index 677ace3945..a08d16380d 100644
> --- a/include/sysemu/watchdog.h
> +++ b/include/sysemu/watchdog.h
> @@ -23,7 +23,7 @@
>  #define QEMU_WATCHDOG_H
>
>  #include "qemu/queue.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-run-state.h"
>
>  struct WatchdogTimerModel {
>      QLIST_ENTRY(WatchdogTimerModel) entry;
> diff --git a/include/ui/input.h b/include/ui/input.h
> index ceb22b8eef..16395ab8f2 100644
> --- a/include/ui/input.h
> +++ b/include/ui/input.h
> @@ -1,7 +1,7 @@
>  #ifndef INPUT_H
>  #define INPUT_H
>
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-ui.h"
>
>  #define INPUT_EVENT_MASK_KEY   (1<<INPUT_EVENT_KIND_KEY)
>  #define INPUT_EVENT_MASK_BTN   (1<<INPUT_EVENT_KIND_BTN)
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index 563e297357..8359b6683a 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -20,6 +20,7 @@
>
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "io/channel-socket.h"
>  #include "io/channel-watch.h"
>  #include "trace.h"
> diff --git a/io/dns-resolver.c b/io/dns-resolver.c
> index c072d121c3..8c924071c4 100644
> --- a/io/dns-resolver.c
> +++ b/io/dns-resolver.c
> @@ -21,6 +21,7 @@
>  #include "qemu/osdep.h"
>  #include "io/dns-resolver.h"
>  #include "qapi/clone-visitor.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "qemu/sockets.h"
>  #include "qapi/error.h"
>  #include "qemu/cutils.h"
> diff --git a/migration/colo-failover.c b/migration/colo-failover.c
> index 891785cb63..0ae0c41221 100644
> --- a/migration/colo-failover.c
> +++ b/migration/colo-failover.c
> @@ -15,8 +15,8 @@
>  #include "migration/failover.h"
>  #include "qemu/main-loop.h"
>  #include "migration.h"
> -#include "qmp-commands.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-migration.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/error-report.h"
>  #include "trace.h"
> diff --git a/migration/colo.c b/migration/colo.c
> index 245a46d59d..4381067ed4 100644
> --- a/migration/colo.c
> +++ b/migration/colo.c
> @@ -13,6 +13,7 @@
>  #include "qemu/osdep.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-migration.h"
>  #include "qemu-file-channel.h"
>  #include "migration.h"
>  #include "qemu-file.h"
> @@ -24,7 +25,6 @@
>  #include "qemu/error-report.h"
>  #include "migration/failover.h"
>  #include "replication.h"
> -#include "qmp-commands.h"
>
>  static bool vmstate_loading;
>
> diff --git a/migration/migration.c b/migration/migration.c
> index 86d69120a6..d26c5999de 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -31,15 +31,15 @@
>  #include "migration/vmstate.h"
>  #include "block/block.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-migration.h"
> +#include "qapi/qapi-events-migration.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qnull.h"
>  #include "qemu/rcu.h"
>  #include "block.h"
>  #include "postcopy-ram.h"
>  #include "qemu/thread.h"
> -#include "qmp-commands.h"
>  #include "trace.h"
> -#include "qapi-event.h"
>  #include "exec/target_page.h"
>  #include "io/channel-buffer.h"
>  #include "migration/colo.h"
> diff --git a/migration/migration.h b/migration/migration.h
> index 848f638a20..e2f18256c9 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -15,6 +15,7 @@
>  #define QEMU_MIGRATION_H
>
>  #include "qemu-common.h"
> +#include "qapi/qapi-types-migration.h"
>  #include "qemu/thread.h"
>  #include "exec/cpu-common.h"
>  #include "qemu/coroutine_int.h"
> diff --git a/migration/ram.c b/migration/ram.c
> index 8333d8e35e..1b30305faf 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -29,7 +29,6 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include <zlib.h>
> -#include "qapi-event.h"
>  #include "qemu/cutils.h"
>  #include "qemu/bitops.h"
>  #include "qemu/bitmap.h"
> @@ -44,6 +43,7 @@
>  #include "migration/page_cache.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-events-migration.h"
>  #include "qapi/qmp/qerror.h"
>  #include "trace.h"
>  #include "exec/ram_addr.h"
> diff --git a/migration/ram.h b/migration/ram.h
> index f3a227b4fc..53f0021c51 100644
> --- a/migration/ram.h
> +++ b/migration/ram.h
> @@ -30,7 +30,7 @@
>  #define QEMU_MIGRATION_RAM_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-migration.h"
>  #include "exec/cpu-common.h"
>
>  extern MigrationStats ram_counters;
> diff --git a/net/colo-compare.c b/net/colo-compare.c
> index 76e03fdb14..23b2d2c4cc 100644
> --- a/net/colo-compare.c
> +++ b/net/colo-compare.c
> @@ -25,7 +25,6 @@
>  #include "net/queue.h"
>  #include "chardev/char-fe.h"
>  #include "qemu/sockets.h"
> -#include "qapi-visit.h"
>  #include "net/colo.h"
>  #include "sysemu/iothread.h"
>
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index 9ce96aaa35..7c487629f9 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -13,8 +13,8 @@
>  #include "qemu-common.h"
>  #include "qemu/timer.h"
>  #include "qemu/iov.h"
> +#include "qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
> -#include "qapi-visit.h"
>  #include "qom/object.h"
>
>  #define TYPE_FILTER_BUFFER "filter-buffer"
> diff --git a/net/filter-mirror.c b/net/filter-mirror.c
> index bd78e25d12..3a61cf21e8 100644
> --- a/net/filter-mirror.c
> +++ b/net/filter-mirror.c
> @@ -14,7 +14,6 @@
>  #include "net/net.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
> -#include "qapi-visit.h"
>  #include "qom/object.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/error-report.h"
> diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
> index 6201494ceb..62dad2d773 100644
> --- a/net/filter-rewriter.c
> +++ b/net/filter-rewriter.c
> @@ -16,7 +16,6 @@
>  #include "net/net.h"
>  #include "qemu-common.h"
>  #include "qemu/error-report.h"
> -#include "qapi-visit.h"
>  #include "qom/object.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/iov.h"
> diff --git a/net/net.c b/net/net.c
> index 7d42925258..547c499110 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -33,18 +33,18 @@
>
>  #include "monitor/monitor.h"
>  #include "qemu/help_option.h"
> +#include "qapi/qapi-commands-net.h"
> +#include "qapi/qapi-visit-net.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/error-report.h"
>  #include "qemu/sockets.h"
>  #include "qemu/cutils.h"
>  #include "qemu/config-file.h"
> -#include "qmp-commands.h"
>  #include "hw/qdev.h"
>  #include "qemu/iov.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/option.h"
> -#include "qapi-visit.h"
>  #include "qapi/error.h"
>  #include "qapi/opts-visitor.h"
>  #include "sysemu/sysemu.h"
> diff --git a/net/tap_int.h b/net/tap_int.h
> index ae6888f74a..9f931d52d6 100644
> --- a/net/tap_int.h
> +++ b/net/tap_int.h
> @@ -27,7 +27,7 @@
>  #define NET_TAP_INT_H
>
>  #include "qemu-common.h"
> -#include "qapi-types.h"
> +#include "qapi/qapi-types-net.h"
>
>  int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
>               int vnet_hdr_required, int mq_required, Error **errp);
> diff --git a/net/vhost-user.c b/net/vhost-user.c
> index cb45512506..98f3601049 100644
> --- a/net/vhost-user.c
> +++ b/net/vhost-user.c
> @@ -14,10 +14,10 @@
>  #include "net/vhost-user.h"
>  #include "chardev/char-fe.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-net.h"
>  #include "qemu/config-file.h"
>  #include "qemu/error-report.h"
>  #include "qemu/option.h"
> -#include "qmp-commands.h"
>  #include "trace.h"
>
>  typedef struct VhostUserState {
> diff --git a/qemu-img.c b/qemu-img.c
> index 56edc15218..40bf7aa7d1 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -27,7 +27,7 @@
>
>  #include "qemu-version.h"
>  #include "qapi/error.h"
> -#include "qapi-visit.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qobject-output-visitor.h"
>  #include "qapi/qmp/qjson.h"
>  #include "qapi/qmp/qdict.h"
> diff --git a/qom/object.c b/qom/object.c
> index 5dcee4683c..81b4f7ac48 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -16,9 +16,9 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/cutils.h"
>  #include "qapi/visitor.h"
> -#include "qapi-visit.h"
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/string-output-visitor.h"
> +#include "qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
>  #include "trace.h"
>
> diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
> index 43d9aa0946..2f76e1f36d 100644
> --- a/qom/object_interfaces.c
> +++ b/qom/object_interfaces.c
> @@ -5,7 +5,6 @@
>  #include "qom/object_interfaces.h"
>  #include "qemu/module.h"
>  #include "qemu/option.h"
> -#include "qapi-visit.h"
>  #include "qapi/opts-visitor.h"
>  #include "qemu/config-file.h"
>
> diff --git a/replay/replay-input.c b/replay/replay-input.c
> index 3ab1536bf7..6ee8b5f8db 100644
> --- a/replay/replay-input.c
> +++ b/replay/replay-input.c
> @@ -16,6 +16,7 @@
>  #include "qemu/notify.h"
>  #include "ui/input.h"
>  #include "qapi/clone-visitor.h"
> +#include "qapi/qapi-visit-ui.h"
>
>  void replay_save_input_event(InputEvent *evt)
>  {
> diff --git a/replication.h b/replication.h
> index ece6ca6133..8faefe005f 100644
> --- a/replication.h
> +++ b/replication.h
> @@ -15,6 +15,7 @@
>  #ifndef REPLICATION_H
>  #define REPLICATION_H
>
> +#include "qapi/qapi-types-block-core.h"
>  #include "qemu/queue.h"
>
>  typedef struct ReplicationOps ReplicationOps;
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index a43bccb190..953449171b 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -241,6 +241,9 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>
>      def _begin_module(self, name):
>          self._visited_ret_types[self._genc] = set()
> +        commands = self._module_basename('qapi-commands', name)
> +        types = self._module_basename('qapi-types', name)
> +        visit = self._module_basename('qapi-visit', name)
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> @@ -251,18 +254,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>  #include "qapi/qobject-input-visitor.h"
>  #include "qapi/dealloc-visitor.h"
>  #include "qapi/error.h"
> -#include "%(prefix)sqapi-types.h"
> -#include "%(prefix)sqapi-visit.h"
> -#include "%(prefix)sqmp-commands.h"
> +#include "%(visit)s.h"
> +#include "%(commands)s.h"
>
>  ''',
> -                             prefix=self._prefix))
> +                             commands=commands, visit=visit))
>          self._genh.add(mcgen('''
> -#include "%(prefix)sqapi-types.h"
> +#include "%(types)s.h"
>  #include "qapi/qmp/dispatch.h"
>
>  ''',
> -                             prefix=self._prefix))
> +                             types=types))
>
>      def visit_end(self):
>          (genc, genh) = self._module[self._main_module]
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 1e0b990f35..5ad6708491 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -165,24 +165,26 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          return basename
>
>      def _begin_module(self, name):
> +        types = self._module_basename('qapi-types', name)
> +        visit = self._module_basename('qapi-visit', name)
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "%(prefix)sqapi-event.h"
> -#include "%(prefix)sqapi-visit.h"
> +#include "%(visit)s.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qobject-output-visitor.h"
>  #include "qapi/qmp-event.h"
>
>  ''',
> -                             prefix=self._prefix))
> +                             visit=visit, prefix=self._prefix))
>          self._genh.add(mcgen('''
>  #include "qapi/util.h"
> -#include "%(prefix)sqapi-types.h"
> +#include "%(types)s.h"
>
>  ''',
> -                             prefix=self._prefix))
> +                             types=types))
>
>      def visit_end(self):
>          self._genh.add(gen_enum(self._enum_name, self._event_names))
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 59826b1162..2a3c502cf6 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -185,13 +185,15 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>  '''))
>
>      def _begin_module(self, name):
> +        types = self._module_basename('qapi-types', name)
> +        visit = self._module_basename('qapi-visit', name)
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
> -#include "%(prefix)sqapi-types.h"
> -#include "%(prefix)sqapi-visit.h"
> +#include "%(types)s.h"
> +#include "%(visit)s.h"
>  ''',
> -                                      prefix=self._prefix))
> +                                      types=types, visit=visit))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi-builtin-types.h"
>  '''))
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 9b678e7263..de09966643 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -284,20 +284,22 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>                                        prefix=prefix))
>
>      def _begin_module(self, name):
> +        types = self._module_basename('qapi-types', name)
> +        visit = self._module_basename('qapi-visit', name)
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
> -#include "%(prefix)sqapi-visit.h"
> +#include "%(visit)s.h"
>  ''',
> -                                      prefix=self._prefix))
> +                                      visit=visit, prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi-builtin-visit.h"
> -#include "%(prefix)sqapi-types.h"
> +#include "%(types)s.h"
>
>  ''',
> -                                      prefix=self._prefix))
> +                                      types=types))
>
>      def visit_enum_type(self, name, info, values, prefix):
>          self._genh.add(gen_visit_decl(name, scalar=True))
> diff --git a/stubs/tpm.c b/stubs/tpm.c
> index c18aac1c73..6729bc8517 100644
> --- a/stubs/tpm.c
> +++ b/stubs/tpm.c
> @@ -4,9 +4,10 @@
>   * This work is licensed under the terms of the GNU GPL, version 2 or later.
>   * See the COPYING file in the top-level directory.
>   */
> +
>  #include "qemu/osdep.h"
> +#include "qapi/qapi-commands-tpm.h"
>  #include "sysemu/tpm.h"
> -#include "qmp-commands.h"
>
>  int tpm_init(void)
>  {
> diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
> index 0301e9d519..00db81f438 100644
> --- a/target/s390x/kvm.c
> +++ b/target/s390x/kvm.c
> @@ -41,7 +41,6 @@
>  #include "exec/gdbstub.h"
>  #include "exec/address-spaces.h"
>  #include "trace.h"
> -#include "qapi-event.h"
>  #include "hw/s390x/s390-pci-inst.h"
>  #include "hw/s390x/s390-pci-bus.h"
>  #include "hw/s390x/ipl.h"
> diff --git a/tests/test-char.c b/tests/test-char.c
> index b358620911..b3a77af085 100644
> --- a/tests/test-char.c
> +++ b/tests/test-char.c
> @@ -8,9 +8,9 @@
>  #include "chardev/char-mux.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-char.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qom/qom-qobject.h"
> -#include "qmp-commands.h"
>
>  static bool quit;
>
> diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
> index 8012341343..5fbe7e551f 100644
> --- a/tests/test-qmp-event.c
> +++ b/tests/test-qmp-event.c
> @@ -14,7 +14,6 @@
>  #include "qemu/osdep.h"
>
>  #include "qemu-common.h"
> -#include "test-qapi-visit.h"
>  #include "test-qapi-event.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qbool.h"
> diff --git a/tpm.c b/tpm.c
> index d11b10bed8..2db03a09b2 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -15,12 +15,12 @@
>  #include "qemu/osdep.h"
>
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-tpm.h"
>  #include "qapi/qmp/qerror.h"
>  #include "sysemu/tpm_backend.h"
>  #include "sysemu/tpm.h"
>  #include "qemu/config-file.h"
>  #include "qemu/error-report.h"
> -#include "qmp-commands.h"
>
>  static QLIST_HEAD(, TPMBackend) tpm_backends =
>      QLIST_HEAD_INITIALIZER(tpm_backends);
> diff --git a/trace/qmp.c b/trace/qmp.c
> index ccd35cd840..756086c79f 100644
> --- a/trace/qmp.c
> +++ b/trace/qmp.c
> @@ -9,7 +9,7 @@
>
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
> -#include "qmp-commands.h"
> +#include "qapi/qapi-commands-trace.h"
>  #include "trace/control.h"
>
>
> diff --git a/ui/console.c b/ui/console.c
> index 36584d039e..a789b8c408 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -26,9 +26,9 @@
>  #include "ui/console.h"
>  #include "hw/qdev-core.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-ui.h"
>  #include "qemu/option.h"
>  #include "qemu/timer.h"
> -#include "qmp-commands.h"
>  #include "chardev/char-fe.h"
>  #include "trace.h"
>  #include "exec/memory.h"
> diff --git a/ui/input-legacy.c b/ui/input-legacy.c
> index 92b37ccb90..e5d4db1d97 100644
> --- a/ui/input-legacy.c
> +++ b/ui/input-legacy.c
> @@ -23,9 +23,9 @@
>   */
>
>  #include "qemu/osdep.h"
> +#include "qapi/qapi-commands-ui.h"
>  #include "sysemu/sysemu.h"
>  #include "ui/console.h"
> -#include "qmp-commands.h"
>  #include "ui/keymaps.h"
>  #include "ui/input.h"
>
> diff --git a/ui/input.c b/ui/input.c
> index 8bef0fb038..51b1019252 100644
> --- a/ui/input.c
> +++ b/ui/input.c
> @@ -1,9 +1,9 @@
>  #include "qemu/osdep.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-ui.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qemu/error-report.h"
> -#include "qmp-commands.h"
>  #include "trace.h"
>  #include "ui/input.h"
>  #include "ui/console.h"
> diff --git a/ui/spice-core.c b/ui/spice-core.c
> index e449172fe9..ae8921a201 100644
> --- a/ui/spice-core.c
> +++ b/ui/spice-core.c
> @@ -28,14 +28,14 @@
>  #include "qemu/queue.h"
>  #include "qemu-x509.h"
>  #include "qemu/sockets.h"
> -#include "qmp-commands.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-ui.h"
> +#include "qapi/qapi-events-ui.h"
>  #include "qemu/notify.h"
>  #include "qemu/option.h"
>  #include "migration/misc.h"
>  #include "hw/hw.h"
>  #include "ui/spice-display.h"
> -#include "qapi-event.h"
>
>  /* core bits */
>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index c715bae1cf..d6329c8bd5 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -36,7 +36,7 @@
>  #include "qemu/acl.h"
>  #include "qemu/config-file.h"
>  #include "qapi/error.h"
> -#include "qmp-commands.h"
> +#include "qapi/qapi-commands-ui.h"
>  #include "ui/input.h"
>  #include "qapi-event.h"
>  #include "crypto/hash.h"
> diff --git a/ui/vnc.h b/ui/vnc.h
> index 1ca062f332..7b29def77d 100644
> --- a/ui/vnc.h
> +++ b/ui/vnc.h
> @@ -28,6 +28,7 @@
>  #define QEMU_VNC_H
>
>  #include "qemu-common.h"
> +#include "qapi/qapi-types-ui.h"
>  #include "qemu/queue.h"
>  #include "qemu/thread.h"
>  #include "ui/console.h"
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index fbbef69f62..7f13e8a338 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -24,11 +24,11 @@
>  #include "monitor/monitor.h"
>  #include "qapi/clone-visitor.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-visit-sockets.h"
>  #include "qemu/sockets.h"
>  #include "qemu/main-loop.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "qapi/qobject-output-visitor.h"
> -#include "qapi-visit.h"
>  #include "qemu/cutils.h"
>
>  #ifndef AI_ADDRCONFIG
> diff --git a/vl.c b/vl.c
> index 21878496ec..4e8287c507 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -97,7 +97,6 @@ int main(int argc, char **argv)
>  #include "sysemu/kvm.h"
>  #include "sysemu/hax.h"
>  #include "qapi/qobject-input-visitor.h"
> -#include "qapi-visit.h"
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
>  #include "qemu-options.h"
> @@ -122,10 +121,11 @@ int main(int argc, char **argv)
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/opts-visitor.h"
>  #include "qom/object_interfaces.h"
> -#include "qapi-event.h"
>  #include "exec/semihost.h"
>  #include "crypto/init.h"
>  #include "sysemu/replay.h"
> +#include "qapi/qapi-events-run-state.h"
> +#include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qmp/qerror.h"
>  #include "sysemu/iothread.h"
>
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
  2018-02-12 22:27   ` Eric Blake
@ 2018-02-13 16:00   ` Marc-Andre Lureau
  2018-02-19 19:33   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 16:00 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> With modular code generation, putting stuff right into
> qapi-schema.json is a bad idea.  Update writing-qmp-commands.txt
> accordingly.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

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


> ---
>  docs/devel/writing-qmp-commands.txt | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 4f5b24c0c4..776b3b41ca 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -15,8 +15,8 @@ start with docs/interop/qmp-intro.txt.
>  Generally speaking, the following steps should be taken in order to write a
>  new QMP command.
>
> -1. Write the command's and type(s) specification in the QAPI schema file
> -   (qapi-schema.json in the root source directory)
> +1. Define the command and any types it needs in the appropriate QAPI
> +   schema module.
>
>  2. Write the QMP command itself, which is a regular C function. Preferably,
>     the command should be exported by some QEMU subsystem. But it can also be
> @@ -88,8 +88,9 @@ command carries some meaningful action in QEMU but here it will just print
>  Our command will be called "hello-world". It takes no arguments, nor does it
>  return any data.
>
> -The first step is to add the following line to the bottom of the
> -qapi-schema.json file:
> +The first step is defining the command in the appropriate QAPI schema
> +module.  We pick module qapi/misc.json, and add the following line at
> +the bottom:
>
>  { 'command': 'hello-world' }
>
> @@ -245,7 +246,7 @@ This is very important. No QMP command will be accepted in QEMU without proper
>  documentation.
>
>  There are many examples of such documentation in the schema file already, but
> -here goes "hello-world"'s new entry for the qapi-schema.json file:
> +here goes "hello-world"'s new entry for qapi/misc.json:
>
>  ##
>  # @hello-world
> @@ -425,8 +426,7 @@ There are a number of things to be noticed:
>     allocated by the implementation. This is so because the QAPI also generates
>     a function to free its types and it cannot distinguish between dynamically
>     or statically allocated strings
> -6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
> -   otherwise qemu won't build
> +6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
>
>  Time to test the new command. Build qemu, run it as described in the "Testing"
>  section and try this:
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
  2018-02-12 22:29   ` Eric Blake
@ 2018-02-13 16:03   ` Marc-Andre Lureau
  2018-02-19 19:35   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 16:03 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> * Fix guidance on error classes
>
> * Point to generated documentation
>
> * Drop plea for documentation, because the QAPI code generator
>   enforces it since commit 3313b6124b
>
> * Minor tweaks here and there
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

looks good to me,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>


> ---
>  docs/devel/writing-qmp-commands.txt | 25 +++++++++----------------
>  docs/interop/qmp-intro.txt          |  3 ++-
>  2 files changed, 11 insertions(+), 17 deletions(-)
>
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 776b3b41ca..50385eff27 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -36,9 +36,9 @@ very simple and get more complex as we progress.
>  For all the examples in the next sections, the test setup is the same and is
>  shown here.
>
> -First, QEMU should be started as:
> +First, QEMU should be started like this:
>
> -# /path/to/your/source/qemu [...] \
> +# qemu-system-TARGET [...] \
>      -chardev socket,id=qmp,port=4444,host=localhost,server \
>      -mon chardev=qmp,mode=control,pretty=on
>
> @@ -179,7 +179,7 @@ described in the "Testing" section and then send two commands:
>      }
>  }
>
> -You should see "Hello, world" and "we love qemu" in the terminal running qemu,
> +You should see "Hello, world" and "We love qemu" in the terminal running qemu,
>  if you don't see these strings, then something went wrong.
>
>  === Errors ===
> @@ -221,30 +221,23 @@ The QMP server's response should be:
>      }
>  }
>
> -As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR
> -(done by default when using error_setg()). There are two exceptions to
> -this rule:
> +Note that error_setg() produces a "GenericError" class.  In general,
> +all QMP errors should have that error class.  There are two exceptions
> +to this rule:
>
> - 1. A non-generic ErrorClass value exists* for the failure you want to report
> -    (eg. DeviceNotFound)
> + 1. To support a management application's need to recognize a specific
> +    error for special handling
>
> - 2. Management applications have to take special action on the failure you
> -    want to report, hence you have to add a new ErrorClass value so that they
> -    can check for it
> + 2. Backward compatibility
>
>  If the failure you want to report falls into one of the two cases above,
>  use error_set() with a second argument of an ErrorClass value.
>
> - * All existing ErrorClass values are defined in the qapi-schema.json file
> -
>  === Command Documentation ===
>
>  There's only one step missing to make "hello-world"'s implementation complete,
>  and that's its documentation in the schema file.
>
> -This is very important. No QMP command will be accepted in QEMU without proper
> -documentation.
> -
>  There are many examples of such documentation in the schema file already, but
>  here goes "hello-world"'s new entry for qapi/misc.json:
>
> diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
> index adbc94abb1..430fe1b747 100644
> --- a/docs/interop/qmp-intro.txt
> +++ b/docs/interop/qmp-intro.txt
> @@ -78,7 +78,8 @@ Escape character is '^]'.
>      }
>  }
>
> -Please, refer to the qapi-schema.json file for a complete command reference.
> +Please refer to docs/interop/qemu-qmp-ref.* for a complete command
> +reference, generated from qapi-schema.json.
>
>  QMP wiki page
>  -------------
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
  2018-02-12 22:36   ` Eric Blake
@ 2018-02-13 16:08   ` Marc-Andre Lureau
  2018-02-19 19:37   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 16:08 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Move qapi-schema.json to qapi/, so it's next to its modules, and all
> files get generated to qapi/, not just the ones generated for modules.
>
> Consistently name the generated files qapi-MODULE.EXT:
> qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become
> qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch].
> This gets rid of the temporary hacks in scripts/qapi/commands.py and
> scripts/qapi/events.py.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>


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


> ---
>  .gitignore                                | 16 ++++++------
>  Makefile                                  | 42 +++++++++++++++----------------
>  Makefile.objs                             | 21 ++++++++--------
>  backends/hostmem.c                        |  2 +-
>  docs/devel/qapi-code-gen.txt              | 30 +++++++++++-----------
>  docs/devel/writing-qmp-commands.txt       |  2 +-
>  docs/interop/qmp-intro.txt                |  2 +-
>  hmp.c                                     |  2 +-
>  include/qapi/qmp/qobject.h                |  2 +-
>  include/qapi/visitor.h                    |  2 +-
>  include/qom/object.h                      |  2 +-
>  monitor.c                                 |  6 ++---
>  net/filter-buffer.c                       |  2 +-
>  qapi/misc.json                            |  4 +--
>  qapi-schema.json => qapi/qapi-schema.json | 32 +++++++++++------------
>  qga/Makefile.objs                         |  2 +-
>  qga/commands-posix.c                      |  2 +-
>  qga/commands-win32.c                      |  2 +-
>  qga/commands.c                            |  2 +-
>  qga/main.c                                |  2 +-
>  qom/object.c                              |  2 +-
>  scripts/qapi/commands.py                  |  7 ------
>  scripts/qapi/events.py                    |  9 +------
>  scripts/qapi/introspect.py                |  4 +--
>  scripts/qapi/types.py                     |  6 ++---
>  scripts/qapi/visit.py                     |  6 ++---
>  tests/.gitignore                          |  6 ++---
>  tests/Makefile.include                    | 14 +++++------
>  tests/test-qmp-cmds.c                     |  2 +-
>  tests/test-qmp-event.c                    |  2 +-
>  tests/test-qobject-input-visitor.c        |  6 ++---
>  tpm.c                                     |  1 -
>  ui/cocoa.m                                |  2 +-
>  ui/vnc.c                                  |  2 +-
>  34 files changed, 116 insertions(+), 130 deletions(-)
>  rename qapi-schema.json => qapi/qapi-schema.json (85%)
>
> diff --git a/.gitignore b/.gitignore
> index 7f162e862f..dabfe6bea8 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -29,8 +29,8 @@
>  /qga/qapi-generated
>  /qapi-generated
>  /qapi-gen-timestamp
> -/qapi-builtin-types.[ch]
> -/qapi-builtin-visit.[ch]
> +/qapi/qapi-builtin-types.[ch]
> +/qapi/qapi-builtin-visit.[ch]
>  /qapi/qapi-commands-block-core.[ch]
>  /qapi/qapi-commands-block.[ch]
>  /qapi/qapi-commands-char.[ch]
> @@ -47,6 +47,7 @@
>  /qapi/qapi-commands-trace.[ch]
>  /qapi/qapi-commands-transaction.[ch]
>  /qapi/qapi-commands-ui.[ch]
> +/qapi/qapi-commands.[ch]
>  /qapi/qapi-events-block-core.[ch]
>  /qapi/qapi-events-block.[ch]
>  /qapi/qapi-events-char.[ch]
> @@ -63,6 +64,8 @@
>  /qapi/qapi-events-trace.[ch]
>  /qapi/qapi-events-transaction.[ch]
>  /qapi/qapi-events-ui.[ch]
> +/qapi/qapi-events.[ch]
> +/qapi/qapi-introspect.[ch]
>  /qapi/qapi-types-block-core.[ch]
>  /qapi/qapi-types-block.[ch]
>  /qapi/qapi-types-char.[ch]
> @@ -79,7 +82,7 @@
>  /qapi/qapi-types-trace.[ch]
>  /qapi/qapi-types-transaction.[ch]
>  /qapi/qapi-types-ui.[ch]
> -/qapi-types.[ch]
> +/qapi/qapi-types.[ch]
>  /qapi/qapi-visit-block-core.[ch]
>  /qapi/qapi-visit-block.[ch]
>  /qapi/qapi-visit-char.[ch]
> @@ -96,11 +99,8 @@
>  /qapi/qapi-visit-trace.[ch]
>  /qapi/qapi-visit-transaction.[ch]
>  /qapi/qapi-visit-ui.[ch]
> -/qapi-visit.[ch]
> -/qapi-event.[ch]
> -/qapi-doc.texi
> -/qmp-commands.[ch]
> -/qmp-introspect.[ch]
> +/qapi/qapi-visit.[ch]
> +/qapi/qapi-doc.texi
>  /qemu-doc.html
>  /qemu-doc.info
>  /qemu-doc.txt
> diff --git a/Makefile b/Makefile
> index 50eb194877..84411ee6ab 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -90,8 +90,8 @@ endif
>  include $(SRC_PATH)/rules.mak
>
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
> -GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
> -GENERATED_FILES += qapi-types.h qapi-types.c
> +GENERATED_FILES += qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
> +GENERATED_FILES += qapi/qapi-types.h qapi/qapi-types.c
>  GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
>  GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c
>  GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c
> @@ -108,8 +108,8 @@ GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c
>  GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c
>  GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c
>  GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c
> -GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
> -GENERATED_FILES += qapi-visit.h qapi-visit.c
> +GENERATED_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c
> +GENERATED_FILES += qapi/qapi-visit.h qapi/qapi-visit.c
>  GENERATED_FILES += qapi/qapi-visit-block-core.h qapi/qapi-visit-block-core.c
>  GENERATED_FILES += qapi/qapi-visit-block.h qapi/qapi-visit-block.c
>  GENERATED_FILES += qapi/qapi-visit-char.h qapi/qapi-visit-char.c
> @@ -126,7 +126,7 @@ GENERATED_FILES += qapi/qapi-visit-tpm.h qapi/qapi-visit-tpm.c
>  GENERATED_FILES += qapi/qapi-visit-trace.h qapi/qapi-visit-trace.c
>  GENERATED_FILES += qapi/qapi-visit-transaction.h qapi/qapi-visit-transaction.c
>  GENERATED_FILES += qapi/qapi-visit-ui.h qapi/qapi-visit-ui.c
> -GENERATED_FILES += qmp-commands.h qmp-commands.c
> +GENERATED_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
>  GENERATED_FILES += qapi/qapi-commands-block-core.h qapi/qapi-commands-block-core.c
>  GENERATED_FILES += qapi/qapi-commands-block.h qapi/qapi-commands-block.c
>  GENERATED_FILES += qapi/qapi-commands-char.h qapi/qapi-commands-char.c
> @@ -143,7 +143,7 @@ GENERATED_FILES += qapi/qapi-commands-tpm.h qapi/qapi-commands-tpm.c
>  GENERATED_FILES += qapi/qapi-commands-trace.h qapi/qapi-commands-trace.c
>  GENERATED_FILES += qapi/qapi-commands-transaction.h qapi/qapi-commands-transaction.c
>  GENERATED_FILES += qapi/qapi-commands-ui.h qapi/qapi-commands-ui.c
> -GENERATED_FILES += qapi-event.h qapi-event.c
> +GENERATED_FILES += qapi/qapi-events.h qapi/qapi-events.c
>  GENERATED_FILES += qapi/qapi-events-block-core.h qapi/qapi-events-block-core.c
>  GENERATED_FILES += qapi/qapi-events-block.h qapi/qapi-events-block.c
>  GENERATED_FILES += qapi/qapi-events-char.h qapi/qapi-events-char.c
> @@ -160,8 +160,8 @@ GENERATED_FILES += qapi/qapi-events-tpm.h qapi/qapi-events-tpm.c
>  GENERATED_FILES += qapi/qapi-events-trace.h qapi/qapi-events-trace.c
>  GENERATED_FILES += qapi/qapi-events-transaction.h qapi/qapi-events-transaction.c
>  GENERATED_FILES += qapi/qapi-events-ui.h qapi/qapi-events-ui.c
> -GENERATED_FILES += qmp-introspect.c qmp-introspect.h
> -GENERATED_FILES += qapi-doc.texi
> +GENERATED_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
> +GENERATED_FILES += qapi/qapi-doc.texi
>
>  GENERATED_FILES += trace/generated-tcg-tracers.h
>
> @@ -563,7 +563,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
>
>  qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
>  qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
> -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
> +qga/qapi-generated/qga-qapi-commands.h qga/qapi-generated/qga-qapi-commands.c \
>  qga/qapi-generated/qga-qapi-doc.texi: \
>  qga/qapi-generated/qapi-gen-timestamp ;
>  qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
> @@ -572,7 +572,7 @@ qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-p
>                 "GEN","$(@:%-timestamp=%)")
>         @>$@
>
> -qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
> +qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
>                 $(SRC_PATH)/qapi/char.json \
>                 $(SRC_PATH)/qapi/crypto.json \
> @@ -588,8 +588,8 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/transaction.json \
>                 $(SRC_PATH)/qapi/ui.json
>
> -qapi-builtin-types.c qapi-builtin-types.h \
> -qapi-types.c qapi-types.h \
> +qapi/qapi-builtin-types.c qapi/qapi-builtin-types.h \
> +qapi/qapi-types.c qapi/qapi-types.h \
>  qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
>  qapi/qapi-types-block.c qapi/qapi-types-block.h \
>  qapi/qapi-types-char.c qapi/qapi-types-char.h \
> @@ -606,8 +606,8 @@ qapi/qapi-types-tpm.c qapi/qapi-types-tpm.h \
>  qapi/qapi-types-trace.c qapi/qapi-types-trace.h \
>  qapi/qapi-types-transaction.c qapi/qapi-types-transaction.h \
>  qapi/qapi-types-ui.c qapi/qapi-types-ui.h \
> -qapi-builtin-visit.c qapi-builtin-visit.h \
> -qapi-visit.c qapi-visit.h \
> +qapi/qapi-builtin-visit.c qapi/qapi-builtin-visit.h \
> +qapi/qapi-visit.c qapi/qapi-visit.h \
>  qapi/qapi-visit-block-core.c qapi/qapi-visit-block-core.h \
>  qapi/qapi-visit-block.c qapi/qapi-visit-block.h \
>  qapi/qapi-visit-char.c qapi/qapi-visit-char.h \
> @@ -624,7 +624,7 @@ qapi/qapi-visit-tpm.c qapi/qapi-visit-tpm.h \
>  qapi/qapi-visit-trace.c qapi/qapi-visit-trace.h \
>  qapi/qapi-visit-transaction.c qapi/qapi-visit-transaction.h \
>  qapi/qapi-visit-ui.c qapi/qapi-visit-ui.h \
> -qmp-commands.h qmp-commands.c \
> +qapi/qapi-commands.h qapi/qapi-commands.c \
>  qapi/qapi-commands-block-core.c qapi/qapi-commands-block-core.h \
>  qapi/qapi-commands-block.c qapi/qapi-commands-block.h \
>  qapi/qapi-commands-char.c qapi/qapi-commands-char.h \
> @@ -641,7 +641,7 @@ qapi/qapi-commands-tpm.c qapi/qapi-commands-tpm.h \
>  qapi/qapi-commands-trace.c qapi/qapi-commands-trace.h \
>  qapi/qapi-commands-transaction.c qapi/qapi-commands-transaction.h \
>  qapi/qapi-commands-ui.c qapi/qapi-commands-ui.h \
> -qapi-event.c qapi-event.h \
> +qapi/qapi-events.c qapi/qapi-events.h \
>  qapi/qapi-events-block-core.c qapi/qapi-events-block-core.h \
>  qapi/qapi-events-block.c qapi/qapi-events-block.h \
>  qapi/qapi-events-char.c qapi/qapi-events-char.h \
> @@ -658,16 +658,16 @@ qapi/qapi-events-tpm.c qapi/qapi-events-tpm.h \
>  qapi/qapi-events-trace.c qapi/qapi-events-trace.h \
>  qapi/qapi-events-transaction.c qapi/qapi-events-transaction.h \
>  qapi/qapi-events-ui.c qapi/qapi-events-ui.h \
> -qmp-introspect.h qmp-introspect.c \
> -qapi-doc.texi: \
> +qapi/qapi-introspect.h qapi/qapi-introspect.c \
> +qapi/qapi-doc.texi: \
>  qapi-gen-timestamp ;
>  qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
>         $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
> -               -o "." -b $<, \
> +               -o "qapi" -b $<, \
>                 "GEN","$(@:%-timestamp=%)")
>         @>$@
>
> -QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
> +QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h)
>  $(qga-obj-y): $(QGALIB_GEN)
>
>  qemu-ga$(EXESUF): $(qga-obj-y) $(COMMON_LDADDS)
> @@ -934,7 +934,7 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt
>  qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
>         $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
>
> -docs/interop/qemu-qmp-qapi.texi: qapi-doc.texi
> +docs/interop/qemu-qmp-qapi.texi: qapi/qapi-doc.texi
>         @cp -p $< $@
>
>  docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi
> diff --git a/Makefile.objs b/Makefile.objs
> index a7986bbf0b..9aa1024c34 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -2,8 +2,8 @@
>  # Common libraries for tools and emulators
>  stub-obj-y = stubs/ crypto/
>  util-obj-y = util/ qobject/ qapi/
> -util-obj-y += qapi-builtin-types.o
> -util-obj-y += qapi-types.o
> +util-obj-y += qapi/qapi-builtin-types.o
> +util-obj-y += qapi/qapi-types.o
>  util-obj-y += qapi/qapi-types-block-core.o
>  util-obj-y += qapi/qapi-types-block.o
>  util-obj-y += qapi/qapi-types-char.o
> @@ -20,8 +20,8 @@ util-obj-y += qapi/qapi-types-tpm.o
>  util-obj-y += qapi/qapi-types-trace.o
>  util-obj-y += qapi/qapi-types-transaction.o
>  util-obj-y += qapi/qapi-types-ui.o
> -util-obj-y += qapi-builtin-visit.o
> -util-obj-y += qapi-visit.o
> +util-obj-y += qapi/qapi-builtin-visit.o
> +util-obj-y += qapi/qapi-visit.o
>  util-obj-y += qapi/qapi-visit-block-core.o
>  util-obj-y += qapi/qapi-visit-block.o
>  util-obj-y += qapi/qapi-visit-char.o
> @@ -38,7 +38,7 @@ util-obj-y += qapi/qapi-visit-tpm.o
>  util-obj-y += qapi/qapi-visit-trace.o
>  util-obj-y += qapi/qapi-visit-transaction.o
>  util-obj-y += qapi/qapi-visit-ui.o
> -util-obj-y += qapi-event.o
> +util-obj-y += qapi/qapi-events.o
>  util-obj-y += qapi/qapi-events-block-core.o
>  util-obj-y += qapi/qapi-events-block.o
>  util-obj-y += qapi/qapi-events-char.o
> @@ -55,7 +55,7 @@ util-obj-y += qapi/qapi-events-tpm.o
>  util-obj-y += qapi/qapi-events-trace.o
>  util-obj-y += qapi/qapi-events-transaction.o
>  util-obj-y += qapi/qapi-events-ui.o
> -util-obj-y += qmp-introspect.o
> +util-obj-y += qapi/qapi-introspect.o
>
>  chardev-obj-y = chardev/
>
> @@ -131,7 +131,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
>  ######################################################################
>  # qapi
>
> -common-obj-y += qmp-commands.o
> +common-obj-y += qapi/qapi-commands.o
>  common-obj-y += qapi/qapi-commands-block-core.o
>  common-obj-y += qapi/qapi-commands-block.o
>  common-obj-y += qapi/qapi-commands-char.o
> @@ -148,7 +148,7 @@ common-obj-y += qapi/qapi-commands-tpm.o
>  common-obj-y += qapi/qapi-commands-trace.o
>  common-obj-y += qapi/qapi-commands-transaction.o
>  common-obj-y += qapi/qapi-commands-ui.o
> -common-obj-y += qmp-introspect.o
> +common-obj-y += qapi/qapi-introspect.o
>  common-obj-y += qmp.o hmp.o
>  endif
>
> @@ -171,8 +171,9 @@ target-obj-y += trace/
>  ######################################################################
>  # guest agent
>
> -# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
> -# by libqemuutil.a.  These should be moved to a separate .json schema.
> +# FIXME: a few definitions from qapi/qapi-types.o and
> +# qapi/qapi-visit.o are needed by libqemuutil.a.  These should be
> +# extracted into a QAPI schema module, or perhaps a separate schema.
>  qga-obj-y = qga/
>  qga-vss-dll-obj-y = qga/
>
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 0afaf7160a..1292a9da1e 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -14,7 +14,7 @@
>  #include "sysemu/hostmem.h"
>  #include "hw/boards.h"
>  #include "qapi/error.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/visitor.h"
>  #include "qemu/config-file.h"
>  #include "qom/object_interfaces.h"
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index ba1dc73298..0c4fc342fe 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -647,7 +647,7 @@ name an event 'MAX', since the generator also produces a C enumeration
>  of all event names with a generated _MAX value at the end.  When
>  'data' is also specified, additional info will be included in the
>  event, with similar semantics to a 'struct' expression.  Finally there
> -will be C API generated in qapi-event.h; when called by QEMU code, a
> +will be C API generated in qapi-events.h; when called by QEMU code, a
>  message with timestamp will be emitted on the wire.
>
>  An example event is:
> @@ -1147,15 +1147,15 @@ declares qmp_COMMAND() that the user must implement.
>
>  The following files are generated:
>
> -$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
> -                         QMP command defined in the schema
> +$(prefix)qapi-commands.c: Command marshal/dispatch functions for each
> +                          QMP command defined in the schema
>
> -$(prefix)qmp-commands.h: Function prototypes for the QMP commands
> -                         specified in the schema
> +$(prefix)qapi-commands.h: Function prototypes for the QMP commands
> +                          specified in the schema
>
>  Example:
>
> -    $ cat qapi-generated/example-qmp-commands.h
> +    $ cat qapi-generated/example-qapi-commands.h
>  [Uninteresting stuff omitted...]
>
>      #ifndef EXAMPLE_QMP_COMMANDS_H
> @@ -1170,7 +1170,7 @@ Example:
>      void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
>
>      #endif
> -    $ cat qapi-generated/example-qmp-commands.c
> +    $ cat qapi-generated/example-qapi-commands.c
>  [Uninteresting stuff omitted...]
>
>      static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
> @@ -1243,14 +1243,14 @@ qapi_event_send_EVENT().
>
>  The following files are created:
>
> -$(prefix)qapi-event.h - Function prototypes for each event type, plus an
> +$(prefix)qapi-events.h - Function prototypes for each event type, plus an
>                          enumeration of all event names
>
> -$(prefix)qapi-event.c - Implementation of functions to send an event
> +$(prefix)qapi-events.c - Implementation of functions to send an event
>
>  Example:
>
> -    $ cat qapi-generated/example-qapi-event.h
> +    $ cat qapi-generated/example-qapi-events.h
>  [Uninteresting stuff omitted...]
>
>      #ifndef EXAMPLE_QAPI_EVENT_H
> @@ -1273,7 +1273,7 @@ Example:
>      extern const char *const example_QAPIEvent_lookup[];
>
>      #endif
> -    $ cat qapi-generated/example-qapi-event.c
> +    $ cat qapi-generated/example-qapi-events.c
>  [Uninteresting stuff omitted...]
>
>      void qapi_event_send_my_event(Error **errp)
> @@ -1305,14 +1305,14 @@ Example:
>
>  The following files are created:
>
> -$(prefix)qmp-introspect.c - Defines a string holding a JSON
> +$(prefix)qapi-introspect.c - Defines a string holding a JSON
>                              description of the schema
>
> -$(prefix)qmp-introspect.h - Declares the above string
> +$(prefix)qapi-introspect.h - Declares the above string
>
>  Example:
>
> -    $ cat qapi-generated/example-qmp-introspect.h
> +    $ cat qapi-generated/example-qapi-introspect.h
>  [Uninteresting stuff omitted...]
>
>      #ifndef EXAMPLE_QMP_INTROSPECT_H
> @@ -1321,7 +1321,7 @@ Example:
>      extern const char example_qmp_schema_json[];
>
>      #endif
> -    $ cat qapi-generated/example-qmp-introspect.c
> +    $ cat qapi-generated/example-qapi-introspect.c
>  [Uninteresting stuff omitted...]
>
>      const char example_qmp_schema_json[] = "["
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 50385eff27..9dfc62bf5a 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -419,7 +419,7 @@ There are a number of things to be noticed:
>     allocated by the implementation. This is so because the QAPI also generates
>     a function to free its types and it cannot distinguish between dynamically
>     or statically allocated strings
> -6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
> +6. You have to include "qapi/qapi-commands-misc.h" in qemu-timer.c
>
>  Time to test the new command. Build qemu, run it as described in the "Testing"
>  section and try this:
> diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
> index 430fe1b747..900d69d612 100644
> --- a/docs/interop/qmp-intro.txt
> +++ b/docs/interop/qmp-intro.txt
> @@ -79,7 +79,7 @@ Escape character is '^]'.
>  }
>
>  Please refer to docs/interop/qemu-qmp-ref.* for a complete command
> -reference, generated from qapi-schema.json.
> +reference, generated from qapi/qapi-schema.json.
>
>  QMP wiki page
>  -------------
> diff --git a/hmp.c b/hmp.c
> index c86946866b..1f31de3217 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -28,7 +28,7 @@
>  #include "monitor/qdev.h"
>  #include "qapi/error.h"
>  #include "qapi/opts-visitor.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qapi-commands-block.h"
>  #include "qapi/qapi-commands-char.h"
>  #include "qapi/qapi-commands-migration.h"
> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
> index a2964fbf25..012439a2e3 100644
> --- a/include/qapi/qmp/qobject.h
> +++ b/include/qapi/qmp/qobject.h
> @@ -32,7 +32,7 @@
>  #ifndef QOBJECT_H
>  #define QOBJECT_H
>
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>
>  struct QObject {
>      QType type;
> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
> index 9e57508446..5b2ed3f202 100644
> --- a/include/qapi/visitor.h
> +++ b/include/qapi/visitor.h
> @@ -15,7 +15,7 @@
>  #ifndef QAPI_VISITOR_H
>  #define QAPI_VISITOR_H
>
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>
>  /*
>   * The QAPI schema defines both a set of C data types, and a QMP wire
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 5b5c016d8f..30db296af4 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -14,7 +14,7 @@
>  #ifndef QEMU_OBJECT_H
>  #define QEMU_OBJECT_H
>
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>  #include "qemu/queue.h"
>
>  struct TypeImpl;
> diff --git a/monitor.c b/monitor.c
> index df670f3e15..d0e8d350fd 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -69,14 +69,14 @@
>  #include "exec/exec-all.h"
>  #include "qemu/log.h"
>  #include "qemu/option.h"
> -#include "qmp-commands.h"
>  #include "hmp.h"
>  #include "qemu/thread.h"
>  #include "block/qapi.h"
> +#include "qapi/qapi-commands.h"
> +#include "qapi/qapi-events.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp-event.h"
> -#include "qapi-event.h"
> -#include "qmp-introspect.h"
> +#include "qapi/qapi-introspect.h"
>  #include "sysemu/qtest.h"
>  #include "sysemu/cpus.h"
>  #include "qemu/cutils.h"
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index 7c487629f9..f7265c50a8 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -13,7 +13,7 @@
>  #include "qemu-common.h"
>  #include "qemu/timer.h"
>  #include "qemu/iov.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qom/object.h"
>
> diff --git a/qapi/misc.json b/qapi/misc.json
> index 225631bf7d..506f2b9371 100644
> --- a/qapi/misc.json
> +++ b/qapi/misc.json
> @@ -1618,7 +1618,7 @@
>  #
>  # Emitted when background dump has completed
>  #
> -# @result: DumpQueryResult type described in qapi-schema.json.
> +# @result: final dump status
>  #
>  # @error: human-readable error string that provides
>  #         hint on why dump failed. Only presents on failure. The
> @@ -2833,7 +2833,7 @@
>  #
>  # Emitted when guest executes ACPI _OST method.
>  #
> -# @info: ACPIOSTInfo type as described in qapi-schema.json
> +# @info: OSPM Status Indication
>  #
>  # Since: 2.1
>  #
> diff --git a/qapi-schema.json b/qapi/qapi-schema.json
> similarity index 85%
> rename from qapi-schema.json
> rename to qapi/qapi-schema.json
> index 689d06c530..25bce78352 100644
> --- a/qapi-schema.json
> +++ b/qapi/qapi-schema.json
> @@ -76,20 +76,20 @@
>  # included sub-schemas inserted at the first include directive
>  # (subsequent include directives have no effect).  To get a sane and
>  # stable order, it's best to include each sub-schema just once, or
> -# include it first in qapi-schema.json.
> +# include it first right here.
>
> -{ 'include': 'qapi/common.json' }
> -{ 'include': 'qapi/sockets.json' }
> -{ 'include': 'qapi/run-state.json' }
> -{ 'include': 'qapi/crypto.json' }
> -{ 'include': 'qapi/block.json' }
> -{ 'include': 'qapi/char.json' }
> -{ 'include': 'qapi/net.json' }
> -{ 'include': 'qapi/rocker.json' }
> -{ 'include': 'qapi/tpm.json' }
> -{ 'include': 'qapi/ui.json' }
> -{ 'include': 'qapi/migration.json' }
> -{ 'include': 'qapi/transaction.json' }
> -{ 'include': 'qapi/trace.json' }
> -{ 'include': 'qapi/introspect.json' }
> -{ 'include': 'qapi/misc.json' }
> +{ 'include': 'common.json' }
> +{ 'include': 'sockets.json' }
> +{ 'include': 'run-state.json' }
> +{ 'include': 'crypto.json' }
> +{ 'include': 'block.json' }
> +{ 'include': 'char.json' }
> +{ 'include': 'net.json' }
> +{ 'include': 'rocker.json' }
> +{ 'include': 'tpm.json' }
> +{ 'include': 'ui.json' }
> +{ 'include': 'migration.json' }
> +{ 'include': 'transaction.json' }
> +{ 'include': 'trace.json' }
> +{ 'include': 'introspect.json' }
> +{ 'include': 'misc.json' }
> diff --git a/qga/Makefile.objs b/qga/Makefile.objs
> index 6151378ae4..ed08c5917c 100644
> --- a/qga/Makefile.objs
> +++ b/qga/Makefile.objs
> @@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
>  qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
>  qga-obj-$(CONFIG_WIN32) += vss-win32.o
>  qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
> -qga-obj-y += qapi-generated/qga-qmp-commands.o
> +qga-obj-y += qapi-generated/qga-qapi-commands.o
>
>  qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 88807f3c78..417a50ce5f 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -17,7 +17,7 @@
>  #include <sys/wait.h>
>  #include <dirent.h>
>  #include "qga/guest-agent-core.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/queue.h"
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index bedae32957..2d48394748 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -34,7 +34,7 @@
>
>  #include "qga/guest-agent-core.h"
>  #include "qga/vss-win32.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/queue.h"
> diff --git a/qga/commands.c b/qga/commands.c
> index 6d710dbb20..a64b34ccab 100644
> --- a/qga/commands.c
> +++ b/qga/commands.c
> @@ -12,7 +12,7 @@
>
>  #include "qemu/osdep.h"
>  #include "qga/guest-agent-core.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/base64.h"
> diff --git a/qga/main.c b/qga/main.c
> index cb434d8c46..f9c83050c5 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -25,7 +25,7 @@
>  #include "qapi/qmp/qstring.h"
>  #include "qga/guest-agent-core.h"
>  #include "qemu/module.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/error.h"
>  #include "qga/channel.h"
> diff --git a/qom/object.c b/qom/object.c
> index 81b4f7ac48..f70a75c308 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -18,7 +18,7 @@
>  #include "qapi/visitor.h"
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/string-output-visitor.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
>  #include "trace.h"
>
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index 953449171b..21a7e0dbe6 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -232,13 +232,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>          self._regy = ''
>          self._visited_ret_types = {}
>
> -    # Temporary HACK:
> -    def _module_basename(self, what, name):
> -        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
> -        if name == self._main_module:
> -            return re.sub(r'qapi-commands', 'qmp-commands', basename)
> -        return basename
> -
>      def _begin_module(self, name):
>          self._visited_ret_types[self._genc] = set()
>          commands = self._module_basename('qapi-commands', name)
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 5ad6708491..3dc523cf39 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -157,20 +157,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
>          self._event_names = []
>
> -    # Temporary HACK:
> -    def _module_basename(self, what, name):
> -        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
> -        if name == self._main_module:
> -            return re.sub(r'qapi-events', 'qapi-event', basename)
> -        return basename
> -
>      def _begin_module(self, name):
>          types = self._module_basename('qapi-types', name)
>          visit = self._module_basename('qapi-visit', name)
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> -#include "%(prefix)sqapi-event.h"
> +#include "%(prefix)sqapi-events.h"
>  #include "%(visit)s.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index f571cc134c..f66c397fb0 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -44,7 +44,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
>
>      def __init__(self, prefix, unmask):
>          QAPISchemaMonolithicCVisitor.__init__(
> -            self, prefix, 'qmp-introspect',
> +            self, prefix, 'qapi-introspect',
>              ' * QAPI/QMP schema introspection', __doc__)
>          self._unmask = unmask
>          self._schema = None
> @@ -53,7 +53,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
>          self._name_map = {}
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
> -#include "%(prefix)sqmp-introspect.h"
> +#include "%(prefix)sqapi-introspect.h"
>
>  ''',
>                               prefix=prefix))
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 2a3c502cf6..64d9c0fb37 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -177,8 +177,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
> -#include "qapi-builtin-types.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-visit.h"
>  '''))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi/util.h"
> @@ -195,7 +195,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>  ''',
>                                        types=types, visit=visit))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>  '''))
>
>      def visit_begin(self, schema):
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index de09966643..5d72d8936c 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -274,11 +274,11 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  '''))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi/visitor.h"
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>
>  ''',
>                                        prefix=prefix))
> @@ -295,7 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>  ''',
>                                        visit=visit, prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "%(types)s.h"
>
>  ''',
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 2629cfc2f9..18e58b2183 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -60,7 +60,8 @@ test-keyval
>  test-logging
>  test-mul64
>  test-opts-visitor
> -test-qapi-event.[ch]
> +test-qapi-commands.[ch]
> +test-qapi-events.[ch]
>  test-qapi-types.[ch]
>  test-qapi-util
>  test-qapi-visit.[ch]
> @@ -71,11 +72,10 @@ test-qga
>  test-qht
>  test-qht-par
>  test-qmp-cmds
> -test-qmp-commands.[ch]
>  test-qmp-event
>  test-qobject-input-strict
>  test-qobject-input-visitor
> -test-qmp-introspect.[ch]
> +test-qapi-introspect.[ch]
>  test-qobject-output-visitor
>  test-rcu-list
>  test-replication
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 9a21ed7ee9..d71adf3996 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -566,8 +566,8 @@ qapi-schema += unknown-expr-key.json
>  check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema))
>
>  GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
> -       tests/test-qmp-commands.h tests/test-qapi-event.h \
> -       tests/test-qmp-introspect.h
> +       tests/test-qapi-commands.h tests/test-qapi-events.h \
> +       tests/test-qapi-introspect.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-qobject.o \
> @@ -592,7 +592,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/tests
>  test-util-obj-y = libqemuutil.a
>  test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
>  test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
> -       tests/test-qapi-event.o tests/test-qmp-introspect.o \
> +       tests/test-qapi-events.o tests/test-qapi-introspect.o \
>         $(test-qom-obj-y)
>  benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
>  test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
> @@ -656,9 +656,9 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
>
>  tests/test-qapi-types.c tests/test-qapi-types.h \
>  tests/test-qapi-visit.c tests/test-qapi-visit.h \
> -tests/test-qmp-commands.h tests/test-qmp-commands.c \
> -tests/test-qapi-event.c tests/test-qapi-event.h \
> -tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
> +tests/test-qapi-commands.h tests/test-qapi-commands.c \
> +tests/test-qapi-events.c tests/test-qapi-events.h \
> +tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \
>  tests/test-qapi-gen-timestamp ;
>  tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
>         $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
> @@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
>  tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
>  tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
>  tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
> -tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
> +tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o $(test-qapi-obj-y)
>  tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
>  tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
>
> diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
> index 24660d0868..5b1cee6912 100644
> --- a/tests/test-qmp-cmds.c
> +++ b/tests/test-qmp-cmds.c
> @@ -3,12 +3,12 @@
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
> -#include "test-qmp-commands.h"
>  #include "qapi/error.h"
>  #include "qemu/module.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "tests/test-qapi-types.h"
>  #include "tests/test-qapi-visit.h"
> +#include "test-qapi-commands.h"
>
>  static QmpCommandList qmp_commands;
>
> diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
> index 5fbe7e551f..31f35b3e66 100644
> --- a/tests/test-qmp-event.c
> +++ b/tests/test-qmp-event.c
> @@ -14,13 +14,13 @@
>  #include "qemu/osdep.h"
>
>  #include "qemu-common.h"
> -#include "test-qapi-event.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp-event.h"
> +#include "test-qapi-events.h"
>
>  typedef struct TestEventData {
>      QDict *expect;
> diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> index d3a56bd071..79b1a8cb17 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -24,8 +24,8 @@
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp/qjson.h"
> -#include "test-qmp-introspect.h"
> -#include "qmp-introspect.h"
> +#include "test-qapi-introspect.h"
> +#include "qapi/qapi-introspect.h"
>
>  typedef struct TestInputVisitorData {
>      QObject *obj;
> @@ -1376,7 +1376,7 @@ int main(int argc, char **argv)
>                             NULL, test_visitor_in_fail_alternate);
>      input_visitor_test_add("/visitor/input/fail/union-native-list",
>                             NULL, test_visitor_in_fail_union_native_list);
> -    input_visitor_test_add("/visitor/input/qmp-introspect",
> +    input_visitor_test_add("/visitor/input/qapi-introspect",
>                             NULL, test_visitor_in_qmp_introspect);
>
>      g_test_run();
> diff --git a/tpm.c b/tpm.c
> index 2db03a09b2..ac580e6d47 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -182,7 +182,6 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
>
>  /*
>   * Walk the list of active TPM backends and collect information about them
> - * following the schema description in qapi-schema.json.
>   */
>  TPMInfoList *qmp_query_tpm(Error **errp)
>  {
> diff --git a/ui/cocoa.m b/ui/cocoa.m
> index 51db47cd71..de6af6fbb9 100644
> --- a/ui/cocoa.m
> +++ b/ui/cocoa.m
> @@ -32,7 +32,7 @@
>  #include "ui/input.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> -#include "qmp-commands.h"
> +#include "qapi/qapi-commands.h"
>  #include "sysemu/blockdev.h"
>  #include "qemu-version.h"
>  #include <Carbon/Carbon.h>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index d6329c8bd5..20cd9bb63d 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -35,10 +35,10 @@
>  #include "qemu/timer.h"
>  #include "qemu/acl.h"
>  #include "qemu/config-file.h"
> +#include "qapi/qapi-events.h"
>  #include "qapi/error.h"
>  #include "qapi/qapi-commands-ui.h"
>  #include "ui/input.h"
> -#include "qapi-event.h"
>  #include "crypto/hash.h"
>  #include "crypto/tlscredsanon.h"
>  #include "crypto/tlscredsx509.h"
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
  2018-02-12 22:47   ` Eric Blake
@ 2018-02-13 16:12   ` Marc-Andre Lureau
  2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 16:12 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> Fix up the reference to qmp-commands.hx in qmp.c.  Missed in commit
> 5032a16d1d.
>
> Fix up the reference to qmp-commands.txt in
> docs/xen-save-devices-state.txt.  Missed in commit 4d8bb958fa.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  docs/xen-save-devices-state.txt |  3 +--
>  qmp.c                           | 14 +++++++-------
>  2 files changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt
> index a72ecc8081..1912ecad25 100644
> --- a/docs/xen-save-devices-state.txt
> +++ b/docs/xen-save-devices-state.txt
> @@ -8,8 +8,7 @@ These operations are normally used with migration (see migration.txt),
>  however it is also possible to save the state of all devices to file,
>  without saving the RAM or the block devices of the VM.
>
> -This operation is called "xen-save-devices-state" (see
> -qmp-commands.txt)
> +The save operation is available as QMP command xen-save-devices-state.
>
>
>  The binary format used in the file is the following:
> diff --git a/qmp.c b/qmp.c
> index a8d4eba973..ba82e1df9f 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -147,13 +147,13 @@ VncInfo2List *qmp_query_vnc_servers(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.
> + * qmp_unregister_commands_hack() ensures that QMP command query-spice
> + * exists only #ifdef CONFIG_SPICE.  Necessary for an accurate
> + * query-commands result.  However, the QAPI schema is blissfully
> + * unaware of that, and the QAPI code generator happily generates a
> + * dead qmp_marshal_query_spice() that calls qmp_query_spice().
> + * Provide it one, or else linking fails.  FIXME Educate the QAPI
> + * schema on CONFIG_SPICE.
>   */

I hope this comment will go away soon,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>


>  SpiceInfo *qmp_query_spice(Error **errp)
>  {
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
  2018-02-12 22:48   ` Eric Blake
@ 2018-02-13 16:15   ` Marc-Andre Lureau
  2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Marc-Andre Lureau @ 2018-02-13 16:15 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, Michael Roth, marcandre, Blake, Eric

On Sun, Feb 11, 2018 at 10:36 AM, Markus Armbruster <armbru@redhat.com> wrote:
> We used to generate first test and later QGA QAPI code into
> qapi-generated/.  Commit b93b63f574 moved the test code to tests/.
> Commit 54c2e50205 moved the QGA code to qga/qapi-generated/.  The
> directory has been unused since.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

good catch,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>


> ---
>  .gitignore | 1 -
>  Makefile   | 1 -
>  configure  | 1 -
>  3 files changed, 3 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index dabfe6bea8..4055e12ee8 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -27,7 +27,6 @@
>  /libuser
>  /linux-headers/asm
>  /qga/qapi-generated
> -/qapi-generated
>  /qapi-gen-timestamp
>  /qapi/qapi-builtin-types.[ch]
>  /qapi/qapi-builtin-visit.[ch]
> diff --git a/Makefile b/Makefile
> index 84411ee6ab..7eb1ede6f4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -726,7 +726,6 @@ clean:
>         rm -f trace/generated-tracers-dtrace.h*
>         rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
>         rm -f qapi-gen-timestamp
> -       rm -rf qapi-generated
>         rm -rf qga/qapi-generated
>         for d in $(ALL_SUBDIRS); do \
>         if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
> diff --git a/configure b/configure
> index 62562f08cf..f564a1639e 100755
> --- a/configure
> +++ b/configure
> @@ -7015,7 +7015,6 @@ DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-sche
>  DIRS="$DIRS docs docs/interop fsdev scsi"
>  DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
>  DIRS="$DIRS roms/seabios roms/vgabios"
> -DIRS="$DIRS qapi-generated"
>  FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
>  FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
>  FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
> --
> 2.13.6
>

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

* Re: [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
  2018-02-12 19:40   ` Eric Blake
@ 2018-02-16 22:53   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-16 22:53 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:41)
> Each generator carries a copyright notice for the generator itself,
> and another one for the files it generates.  Only the former have been
> updated along the way, the latter have not, and are all out of date.
> 
> Fix by copying the generator's copyright notice to the generated files
> instead.  Note that the fix doesn't copy the "Authors:" part; the
> generated files' outdated Authors list goes away without replacement.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-commands.py   | 34 +++++++++++++++-------------------
>  scripts/qapi-event.py      | 32 ++++++++++++++------------------
>  scripts/qapi-introspect.py | 25 ++++++++++++-------------
>  scripts/qapi-types.py      | 32 ++++++++++++++------------------
>  scripts/qapi-visit.py      | 34 +++++++++++++++-------------------
>  scripts/qapi.py            |  7 +++++--
>  6 files changed, 75 insertions(+), 89 deletions(-)
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 8e8da7c796..84a980d882 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -1,16 +1,17 @@
> -#
> -# QAPI command marshaller generator
> -#
> -# Copyright IBM, Corp. 2011
> -# Copyright (C) 2014-2016 Red Hat, Inc.
> -#
> -# Authors:
> -#  Anthony Liguori <aliguori@us.ibm.com>
> -#  Michael Roth    <mdroth@linux.vnet.ibm.com>
> -#  Markus Armbruster <armbru@redhat.com>
> -#
> -# This work is licensed under the terms of the GNU GPL, version 2.
> -# See the COPYING file in the top-level directory.
> +"""
> +QAPI command marshaller generator
> +
> +Copyright IBM, Corp. 2011
> +Copyright (C) 2014-2018 Red Hat, Inc.
> +
> +Authors:
> + Anthony Liguori <aliguori@us.ibm.com>
> + Michael Roth <mdroth@linux.vnet.ibm.com>
> + Markus Armbruster <armbru@redhat.com>
> +
> +This work is licensed under the terms of the GNU GPL, version 2.
> +See the COPYING file in the top-level directory.
> +"""
> 
>  from qapi import *
> 
> @@ -257,16 +258,11 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> 
>  blurb = '''
>   * Schema-defined QAPI/QMP commands
> - *
> - * Copyright IBM, Corp. 2011
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
>  '''
> 
>  (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>                              'qmp-marshal.c', 'qmp-commands.h',
> -                            blurb)
> +                            blurb, __doc__)
> 
>  fdef.write(mcgen('''
> 
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index 2b7d720c08..0a098803e2 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -1,15 +1,16 @@
> -#
> -# QAPI event generator
> -#
> -# Copyright (c) 2014 Wenchao Xia
> -# Copyright (c) 2015-2016 Red Hat Inc.
> -#
> -# Authors:
> -#  Wenchao Xia <wenchaoqemu@gmail.com>
> -#  Markus Armbruster <armbru@redhat.com>
> -#
> -# This work is licensed under the terms of the GNU GPL, version 2.
> -# See the COPYING file in the top-level directory.
> +"""
> +QAPI event generator
> +
> +Copyright (c) 2014 Wenchao Xia
> +Copyright (c) 2015-2018 Red Hat Inc.
> +
> +Authors:
> + Wenchao Xia <wenchaoqemu@gmail.com>
> + Markus Armbruster <armbru@redhat.com>
> +
> +This work is licensed under the terms of the GNU GPL, version 2.
> +See the COPYING file in the top-level directory.
> +"""
> 
>  from qapi import *
> 
> @@ -173,16 +174,11 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
> 
>  blurb = '''
>   * Schema-defined QAPI/QMP events
> - *
> - * Copyright (c) 2014 Wenchao Xia
> - *
> - * Authors:
> - *  Wenchao Xia   <wenchaoqemu@gmail.com>
>  '''
> 
>  (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>                              'qapi-event.c', 'qapi-event.h',
> -                            blurb)
> +                            blurb, __doc__)
> 
>  fdef.write(mcgen('''
>  #include "qemu/osdep.h"
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 83da2bdb94..bd9253a172 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -1,13 +1,14 @@
> -#
> -# QAPI introspection generator
> -#
> -# Copyright (C) 2015-2016 Red Hat, Inc.
> -#
> -# Authors:
> -#  Markus Armbruster <armbru@redhat.com>
> -#
> -# This work is licensed under the terms of the GNU GPL, version 2.
> -# See the COPYING file in the top-level directory.
> +"""
> +QAPI introspection generator
> +
> +Copyright (C) 2015-2018 Red Hat, Inc.
> +
> +Authors:
> + Markus Armbruster <armbru@redhat.com>
> +
> +This work is licensed under the terms of the GNU GPL, version 2.
> +See the COPYING file in the top-level directory.
> +"""
> 
>  from qapi import *
> 
> @@ -178,13 +179,11 @@ for o, a in opts:
> 
>  blurb = '''
>   * QAPI/QMP schema introspection
> - *
> - * Copyright (C) 2015 Red Hat, Inc.
>  '''
> 
>  (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>                              'qmp-introspect.c', 'qmp-introspect.h',
> -                            blurb)
> +                            blurb, __doc__)
> 
>  fdef.write(mcgen('''
>  #include "qemu/osdep.h"
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index 86afc57f92..1103dbda2d 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -1,15 +1,17 @@
> -#
> -# QAPI types generator
> -#
> -# Copyright IBM, Corp. 2011
> -# Copyright (c) 2013-2016 Red Hat Inc.
> -#
> -# Authors:
> -#  Anthony Liguori <aliguori@us.ibm.com>
> -#  Markus Armbruster <armbru@redhat.com>
> -#
> -# This work is licensed under the terms of the GNU GPL, version 2.
> +"""
> +QAPI types generator
> +
> +Copyright IBM, Corp. 2011
> +Copyright (c) 2013-2018 Red Hat Inc.
> +
> +Authors:
> + Anthony Liguori <aliguori@us.ibm.com>
> + Michael Roth <mdroth@linux.vnet.ibm.com>
> + Markus Armbruster <armbru@redhat.com>
> +
> +This work is licensed under the terms of the GNU GPL, version 2.
>  # See the COPYING file in the top-level directory.
> +"""
> 
>  from qapi import *
> 
> @@ -252,17 +254,11 @@ for o, a in opts:
> 
>  blurb = '''
>   * Schema-defined QAPI types
> - *
> - * Copyright IBM, Corp. 2011
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
> - *  Michael Roth      <mdroth@linux.vnet.ibm.com>
>  '''
> 
>  (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>                              'qapi-types.c', 'qapi-types.h',
> -                            blurb)
> +                            blurb, __doc__)
> 
>  fdef.write(mcgen('''
>  #include "qemu/osdep.h"
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 0a367072fb..e56b3c1256 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -1,16 +1,17 @@
> -#
> -# QAPI visitor generator
> -#
> -# Copyright IBM, Corp. 2011
> -# Copyright (C) 2014-2016 Red Hat, Inc.
> -#
> -# Authors:
> -#  Anthony Liguori <aliguori@us.ibm.com>
> -#  Michael Roth    <mdroth@linux.vnet.ibm.com>
> -#  Markus Armbruster <armbru@redhat.com>
> -#
> -# This work is licensed under the terms of the GNU GPL, version 2.
> -# See the COPYING file in the top-level directory.
> +"""
> +QAPI visitor generator
> +
> +Copyright IBM, Corp. 2011
> +Copyright (C) 2014-2018 Red Hat, Inc.
> +
> +Authors:
> + Anthony Liguori <aliguori@us.ibm.com>
> + Michael Roth    <mdroth@linux.vnet.ibm.com>
> + Markus Armbruster <armbru@redhat.com>
> +
> +This work is licensed under the terms of the GNU GPL, version 2.
> +See the COPYING file in the top-level directory.
> +"""
> 
>  from qapi import *
> 
> @@ -336,16 +337,11 @@ for o, a in opts:
> 
>  blurb = '''
>   * Schema-defined QAPI visitors
> - *
> - * Copyright IBM, Corp. 2011
> - *
> - * Authors:
> - *  Anthony Liguori   <aliguori@us.ibm.com>
>  '''
> 
>  (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>                              'qapi-visit.c', 'qapi-visit.h',
> -                            blurb)
> +                            blurb, __doc__)
> 
>  fdef.write(mcgen('''
>  #include "qemu/osdep.h"
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 2e5a1ce6a8..26c45cee34 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -1985,21 +1985,24 @@ def parse_command_line(extra_options='', extra_long_options=[]):
>  #
> 
> 
> -def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb):
> +def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
>      guard = guardname(prefix + h_file)
>      c_file = output_dir + prefix + c_file
>      h_file = output_dir + prefix + h_file
> +    copyright = '\n * '.join(re.findall(r'^Copyright .*', doc, re.MULTILINE))
>      comment = mcgen('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
> 
>  /*
>  %(blurb)s
>   *
> + * %(copyright)s
> + *
>   * 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.
>   */
> 
>  ''',
> -                    blurb=blurb.strip('\n'))
> +                    blurb=blurb.strip('\n'), copyright=copyright)
> 
>      if output_dir:
>          try:
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
  2018-02-12 16:59   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
@ 2018-02-16 22:56   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-16 22:56 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:42)
> Rename the variable holding the QAPISchemaGenFOOVisitor from gen to
> vis, to avoid confusion in the next commit.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-commands.py   | 8 ++++----
>  scripts/qapi-event.py      | 8 ++++----
>  scripts/qapi-introspect.py | 8 ++++----
>  scripts/qapi-types.py      | 8 ++++----
>  scripts/qapi-visit.py      | 8 ++++----
>  5 files changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 84a980d882..c3aa52fce1 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -291,9 +291,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>                    prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> 
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenCommandVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenCommandVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
> 
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index 0a098803e2..edb9ddb650 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -203,9 +203,9 @@ fdecl.write(mcgen('''
>  event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
> 
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenEventVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenEventVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
> 
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index bd9253a172..ebe8706f41 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -193,9 +193,9 @@ fdef.write(mcgen('''
>                   prefix=prefix))
> 
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenIntrospectVisitor(opt_unmask)
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
> 
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index 1103dbda2d..4db8424da1 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -273,9 +273,9 @@ fdecl.write(mcgen('''
>  '''))
> 
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenTypeVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenTypeVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
> 
>  close_output(fdef, fdecl)
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index e56b3c1256..3c1a0e2544 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -360,9 +360,9 @@ fdecl.write(mcgen('''
>                    prefix=prefix))
> 
>  schema = QAPISchema(input_file)
> -gen = QAPISchemaGenVisitVisitor()
> -schema.visit(gen)
> -fdef.write(gen.defn)
> -fdecl.write(gen.decl)
> +vis = QAPISchemaGenVisitVisitor()
> +schema.visit(vis)
> +fdef.write(vis.defn)
> +fdecl.write(vis.decl)
> 
>  close_output(fdef, fdecl)
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc Markus Armbruster
@ 2018-02-17  0:59   ` Michael Roth
  2018-02-23 17:18     ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Michael Roth @ 2018-02-17  0:59 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:43)
> These classes encapsulate accumulating and writing output.
> 
> Convert C code generation to QAPIGenC and QAPIGenH.  The conversion is
> rather shallow: most of the output accumulation is not converted.
> Left for later.
> 
> The indentation machinery uses a single global variable indent_level,
> even though we generally interleave creation of a .c and its .h.  It
> should become instance variable of QAPIGenC.  Also left for later.
> 
> Documentation generation isn't converted, and QAPIGenDoc isn't used.
> This will change shortly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

2 minor nits below, but in any case:

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-commands.py   | 23 +++++------
>  scripts/qapi-event.py      | 22 ++++++-----
>  scripts/qapi-introspect.py | 18 +++++----
>  scripts/qapi-types.py      | 22 ++++++-----
>  scripts/qapi-visit.py      | 22 ++++++-----
>  scripts/qapi.py            | 99 +++++++++++++++++++++++++---------------------
>  6 files changed, 112 insertions(+), 94 deletions(-)
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index c3aa52fce1..8d38ade076 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -260,12 +260,10 @@ blurb = '''
>   * Schema-defined QAPI/QMP commands
>  '''
> 
> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
> -                            'qmp-marshal.c', 'qmp-commands.h',
> -                            blurb, __doc__)
> -
> -fdef.write(mcgen('''
> +genc = QAPIGenC(blurb, __doc__)
> +genh = QAPIGenH(blurb, __doc__)
> 
> +genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qemu/module.h"
> @@ -280,20 +278,23 @@ fdef.write(mcgen('''
>  #include "%(prefix)sqmp-commands.h"
> 
>  ''',
> -                 prefix=prefix))
> +               prefix=prefix))
> 
> -fdecl.write(mcgen('''
> +genh.add(mcgen('''
>  #include "%(prefix)sqapi-types.h"
>  #include "qapi/qmp/dispatch.h"
> 
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
> -                  prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> +               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> 
>  schema = QAPISchema(input_file)
>  vis = QAPISchemaGenCommandVisitor()
>  schema.visit(vis)
> -fdef.write(vis.defn)
> -fdecl.write(vis.decl)
> +genc.add(vis.defn)
> +genh.add(vis.decl)
> 
> -close_output(fdef, fdecl)
> +if do_c:
> +    genc.write(output_dir, prefix + 'qmp-marshal.c')
> +if do_h:
> +    genh.write(output_dir, prefix + 'qmp-commands.h')
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index edb9ddb650..bd7a9be3dc 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -176,11 +176,10 @@ blurb = '''
>   * Schema-defined QAPI/QMP events
>  '''
> 
> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
> -                            'qapi-event.c', 'qapi-event.h',
> -                            blurb, __doc__)
> +genc = QAPIGenC(blurb, __doc__)
> +genh = QAPIGenH(blurb, __doc__)
> 
> -fdef.write(mcgen('''
> +genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "%(prefix)sqapi-event.h"
> @@ -191,21 +190,24 @@ fdef.write(mcgen('''
>  #include "qapi/qmp-event.h"
> 
>  ''',
> -                 prefix=prefix))
> +               prefix=prefix))
> 
> -fdecl.write(mcgen('''
> +genh.add(mcgen('''
>  #include "qapi/util.h"
>  #include "%(prefix)sqapi-types.h"
> 
>  ''',
> -                  prefix=prefix))
> +               prefix=prefix))
> 
>  event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
> 
>  schema = QAPISchema(input_file)
>  vis = QAPISchemaGenEventVisitor()
>  schema.visit(vis)
> -fdef.write(vis.defn)
> -fdecl.write(vis.decl)
> +genc.add(vis.defn)
> +genh.add(vis.decl)
> 
> -close_output(fdef, fdecl)
> +if do_c:
> +    genc.write(output_dir, prefix + 'qapi-event.c')
> +if do_h:
> +    genh.write(output_dir, prefix + 'qapi-event.h')
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index ebe8706f41..3d65690fe3 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -181,21 +181,23 @@ blurb = '''
>   * QAPI/QMP schema introspection
>  '''
> 
> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
> -                            'qmp-introspect.c', 'qmp-introspect.h',
> -                            blurb, __doc__)
> +genc = QAPIGenC(blurb, __doc__)
> +genh = QAPIGenH(blurb, __doc__)
> 
> -fdef.write(mcgen('''
> +genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "%(prefix)sqmp-introspect.h"
> 
>  ''',
> -                 prefix=prefix))
> +               prefix=prefix))
> 
>  schema = QAPISchema(input_file)
>  vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
>  schema.visit(vis)
> -fdef.write(vis.defn)
> -fdecl.write(vis.decl)
> +genc.add(vis.defn)
> +genh.add(vis.decl)
> 
> -close_output(fdef, fdecl)
> +if do_c:
> +    genc.write(output_dir, prefix + 'qmp-introspect.c')
> +if do_h:
> +    genh.write(output_dir, prefix + 'qmp-introspect.h')
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index 4db8424da1..c0ac879beb 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -180,7 +180,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          self.decl = ''
>          self.defn = ''
>          self._fwdecl = ''
> -        self._btin = guardstart('QAPI_TYPES_BUILTIN')
> +        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')

Minor nit, but if we compensate for guardstart() change here, shouldn't
we do the same in QAPISchemaGenVisitVisitor? Both are cosmetic (though
Visit is in less need since it has extra an extra newline already,
but changing one and not the other to compensate here makes the patch
appear less mechanical, and the resulting formatting fix-up gets dropped
later in the series anyway)

> 
>      def visit_end(self):
>          self.decl = self._fwdecl + self.decl

<snip>

> +class QAPIGenDoc(QAPIGen):
> +    def _top(self, fname):
> +        return (QAPIGen._top(self, fname)
> +                + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')

The whitespace change in
"qapi/types qapi/visit: Generate built-in stuff into separate files" should
probably be squashed in here:

 class QAPIGenDoc(QAPIGen):
+
     def _top(self, fname):
         return (QAPIGen._top(self, fname)
                 + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')

> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some Markus Armbruster
@ 2018-02-17  1:22   ` Michael Roth
  0 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-17  1:22 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:44)
> In preparation of the next commit, which will turn the generators into
> modules.  These global variables will become local to main() then.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-commands.py   |  9 +++++----
>  scripts/qapi-event.py      | 15 +++++++--------
>  scripts/qapi-introspect.py |  7 ++++---
>  scripts/qapi-types.py      | 17 +++++++++--------
>  scripts/qapi-visit.py      | 17 +++++++++--------
>  5 files changed, 34 insertions(+), 31 deletions(-)
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index 8d38ade076..e97e16e828 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -207,7 +207,7 @@ def gen_register_command(name, success_response):
>      return ret
> 
> 
> -def gen_registry(registry):
> +def gen_registry(registry, prefix):
>      ret = mcgen('''
> 
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
> @@ -224,7 +224,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
> 
> 
>  class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
> -    def __init__(self):
> +    def __init__(self, prefix):
> +        self._prefix = prefix
>          self.decl = None
>          self.defn = None
>          self._regy = None
> @@ -237,7 +238,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._visited_ret_types = set()
> 
>      def visit_end(self):
> -        self.defn += gen_registry(self._regy)
> +        self.defn += gen_registry(self._regy, self._prefix)
>          self._regy = None
>          self._visited_ret_types = None
> 
> @@ -289,7 +290,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>                 prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> 
>  schema = QAPISchema(input_file)
> -vis = QAPISchemaGenCommandVisitor()
> +vis = QAPISchemaGenCommandVisitor(prefix)
>  schema.visit(vis)
>  genc.add(vis.defn)
>  genh.add(vis.decl)
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index bd7a9be3dc..3f98e2491a 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -58,7 +58,7 @@ def gen_param_var(typ):
>      return ret
> 
> 
> -def gen_event_send(name, arg_type, boxed):
> +def gen_event_send(name, arg_type, boxed, event_enum_name):
>      # FIXME: Our declaration of local variables (and of 'errp' in the
>      # parameter list) can collide with exploded members of the event's
>      # data type passed in as parameters.  If this collision ever hits in
> @@ -149,7 +149,8 @@ out:
> 
> 
>  class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
> -    def __init__(self):
> +    def __init__(self, prefix):
> +        self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
>          self.decl = None
>          self.defn = None
>          self._event_names = None
> @@ -160,13 +161,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
>          self._event_names = []
> 
>      def visit_end(self):
> -        self.decl += gen_enum(event_enum_name, self._event_names)
> -        self.defn += gen_enum_lookup(event_enum_name, self._event_names)
> +        self.decl += gen_enum(self._enum_name, self._event_names)
> +        self.defn += gen_enum_lookup(self._enum_name, self._event_names)
>          self._event_names = None
> 
>      def visit_event(self, name, info, arg_type, boxed):
>          self.decl += gen_event_send_decl(name, arg_type, boxed)
> -        self.defn += gen_event_send(name, arg_type, boxed)
> +        self.defn += gen_event_send(name, arg_type, boxed, self._enum_name)
>          self._event_names.append(name)
> 
> 
> @@ -199,10 +200,8 @@ genh.add(mcgen('''
>  ''',
>                 prefix=prefix))
> 
> -event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
> -
>  schema = QAPISchema(input_file)
> -vis = QAPISchemaGenEventVisitor()
> +vis = QAPISchemaGenEventVisitor(prefix)
>  schema.visit(vis)
>  genc.add(vis.defn)
>  genh.add(vis.decl)
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 3d65690fe3..2418b80a82 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -41,7 +41,8 @@ def to_c_string(string):
> 
> 
>  class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
> -    def __init__(self, unmask):
> +    def __init__(self, prefix, unmask):
> +        self._prefix = prefix
>          self._unmask = unmask
>          self.defn = None
>          self.decl = None
> @@ -65,7 +66,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
>          # generate C
>          # TODO can generate awfully long lines
>          jsons.extend(self._jsons)
> -        name = c_name(prefix, protect=False) + 'qmp_schema_json'
> +        name = c_name(self._prefix, protect=False) + 'qmp_schema_json'
>          self.decl = mcgen('''
>  extern const char %(c_name)s[];
>  ''',
> @@ -192,7 +193,7 @@ genc.add(mcgen('''
>                 prefix=prefix))
> 
>  schema = QAPISchema(input_file)
> -vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
> +vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
>  schema.visit(vis)
>  genc.add(vis.defn)
>  genh.add(vis.decl)
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index c0ac879beb..5ff2bfcf41 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -168,7 +168,8 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
> 
> 
>  class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
> -    def __init__(self):
> +    def __init__(self, opt_builtins):
> +        self._opt_builtins = opt_builtins
>          self.decl = None
>          self.defn = None
>          self._fwdecl = None
> @@ -187,7 +188,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          self._fwdecl = None
>          # To avoid header dependency hell, we always generate
>          # declarations for built-in types in our header files and
> -        # simply guard them.  See also do_builtins (command line
> +        # simply guard them.  See also opt_builtins (command line
>          # option -b).
>          self._btin += guardend('QAPI_TYPES_BUILTIN')
>          self.decl = self._btin + self.decl
> @@ -202,7 +203,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          # TODO use something cleaner than existence of info
>          if not info:
>              self._btin += gen_enum(name, values, prefix)
> -            if do_builtins:
> +            if self._opt_builtins:
>                  self.defn += gen_enum_lookup(name, values, prefix)
>          else:
>              self._fwdecl += gen_enum(name, values, prefix)
> @@ -213,7 +214,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>              self._btin += gen_fwd_object_or_array(name)
>              self._btin += gen_array(name, element_type)
>              self._btin += gen_type_cleanup_decl(name)
> -            if do_builtins:
> +            if self._opt_builtins:
>                  self.defn += gen_type_cleanup(name)
>          else:
>              self._fwdecl += gen_fwd_object_or_array(name)
> @@ -241,16 +242,16 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
> 
>  # If you link code generated from multiple schemata, you want only one
>  # instance of the code for built-in types.  Generate it only when
> -# do_builtins, enabled by command line option -b.  See also
> +# opt_builtins, enabled by command line option -b.  See also
>  # QAPISchemaGenTypeVisitor.visit_end().
> -do_builtins = False
> +opt_builtins = False
> 
>  (input_file, output_dir, do_c, do_h, prefix, opts) = \
>      parse_command_line('b', ['builtins'])
> 
>  for o, a in opts:
>      if o in ('-b', '--builtins'):
> -        do_builtins = True
> +        opt_builtins = True
> 
>  blurb = '''
>   * Schema-defined QAPI types
> @@ -272,7 +273,7 @@ genh.add(mcgen('''
>  '''))
> 
>  schema = QAPISchema(input_file)
> -vis = QAPISchemaGenTypeVisitor()
> +vis = QAPISchemaGenTypeVisitor(opt_builtins)
>  schema.visit(vis)
>  genc.add(vis.defn)
>  genh.add(vis.decl)
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 888c686303..0a1eff7736 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -264,7 +264,8 @@ out:
> 
> 
>  class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> -    def __init__(self):
> +    def __init__(self, opt_builtins):
> +        self._opt_builtins = opt_builtins
>          self.decl = None
>          self.defn = None
>          self._btin = None
> @@ -277,7 +278,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>      def visit_end(self):
>          # To avoid header dependency hell, we always generate
>          # declarations for built-in types in our header files and
> -        # simply guard them.  See also do_builtins (command line
> +        # simply guard them.  See also opt_builtins (command line
>          # option -b).
>          self._btin += guardend('QAPI_VISIT_BUILTIN')
>          self.decl = self._btin + self.decl
> @@ -288,7 +289,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          # TODO use something cleaner than existence of info
>          if not info:
>              self._btin += gen_visit_decl(name, scalar=True)
> -            if do_builtins:
> +            if self._opt_builtins:
>                  self.defn += gen_visit_enum(name)
>          else:
>              self.decl += gen_visit_decl(name, scalar=True)
> @@ -299,7 +300,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          defn = gen_visit_list(name, element_type)
>          if isinstance(element_type, QAPISchemaBuiltinType):
>              self._btin += decl
> -            if do_builtins:
> +            if self._opt_builtins:
>                  self.defn += defn
>          else:
>              self.decl += decl
> @@ -324,16 +325,16 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
> 
>  # If you link code generated from multiple schemata, you want only one
>  # instance of the code for built-in types.  Generate it only when
> -# do_builtins, enabled by command line option -b.  See also
> +# opt_builtins, enabled by command line option -b.  See also
>  # QAPISchemaGenVisitVisitor.visit_end().
> -do_builtins = False
> +opt_builtins = False
> 
>  (input_file, output_dir, do_c, do_h, prefix, opts) = \
>      parse_command_line('b', ['builtins'])
> 
>  for o, a in opts:
>      if o in ('-b', '--builtins'):
> -        do_builtins = True
> +        opt_builtins = True
> 
>  blurb = '''
>   * Schema-defined QAPI visitors
> @@ -359,7 +360,7 @@ genh.add(mcgen('''
>                 prefix=prefix))
> 
>  schema = QAPISchema(input_file)
> -vis = QAPISchemaGenVisitVisitor()
> +vis = QAPISchemaGenVisitVisitor(opt_builtins)
>  schema.visit(vis)
>  genc.add(vis.defn)
>  genh.add(vis.decl)
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
@ 2018-02-17  1:29   ` Michael Roth
  2018-02-27 15:53   ` Eric Blake
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-17  1:29 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:45)
> The next commit will introduce a common driver program for all
> generators.  The generators need to be modules for that.  qapi2texi.py
> already is.  Make the other generators follow suit.
> 
> The changes are actually trivial.  Obvious in the diffs once you view
> them with whitespace changes ignored.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-commands.py   | 43 ++++++++++++++++++--------------
>  scripts/qapi-event.py      | 43 ++++++++++++++++++--------------
>  scripts/qapi-introspect.py | 54 ++++++++++++++++++++++------------------
>  scripts/qapi-types.py      | 56 ++++++++++++++++++++++-------------------
>  scripts/qapi-visit.py      | 62 +++++++++++++++++++++++++---------------------
>  5 files changed, 143 insertions(+), 115 deletions(-)
> 
> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
> index e97e16e828..8584cb5873 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi-commands.py
> @@ -255,16 +255,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._regy += gen_register_command(name, success_response)
> 
> 
> -(input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> +def main(argv):
> +    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> 
> -blurb = '''
> +    blurb = '''
>   * Schema-defined QAPI/QMP commands
>  '''
> 
> -genc = QAPIGenC(blurb, __doc__)
> -genh = QAPIGenH(blurb, __doc__)
> +    genc = QAPIGenC(blurb, __doc__)
> +    genh = QAPIGenH(blurb, __doc__)
> 
> -genc.add(mcgen('''
> +    genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qemu/module.h"
> @@ -279,23 +280,27 @@ genc.add(mcgen('''
>  #include "%(prefix)sqmp-commands.h"
> 
>  ''',
> -               prefix=prefix))
> +                   prefix=prefix))
> 
> -genh.add(mcgen('''
> +    genh.add(mcgen('''
>  #include "%(prefix)sqapi-types.h"
>  #include "qapi/qmp/dispatch.h"
> 
>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
> -               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> -
> -schema = QAPISchema(input_file)
> -vis = QAPISchemaGenCommandVisitor(prefix)
> -schema.visit(vis)
> -genc.add(vis.defn)
> -genh.add(vis.decl)
> -
> -if do_c:
> -    genc.write(output_dir, prefix + 'qmp-marshal.c')
> -if do_h:
> -    genh.write(output_dir, prefix + 'qmp-commands.h')
> +                   prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> +
> +    schema = QAPISchema(input_file)
> +    vis = QAPISchemaGenCommandVisitor(prefix)
> +    schema.visit(vis)
> +    genc.add(vis.defn)
> +    genh.add(vis.decl)
> +
> +    if do_c:
> +        genc.write(output_dir, prefix + 'qmp-marshal.c')
> +    if do_h:
> +        genh.write(output_dir, prefix + 'qmp-commands.h')
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> index 3f98e2491a..e7e07f0055 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi-event.py
> @@ -171,16 +171,17 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
>          self._event_names.append(name)
> 
> 
> -(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
> +def main(argv):
> +    (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
> 
> -blurb = '''
> +    blurb = '''
>   * Schema-defined QAPI/QMP events
>  '''
> 
> -genc = QAPIGenC(blurb, __doc__)
> -genh = QAPIGenH(blurb, __doc__)
> +    genc = QAPIGenC(blurb, __doc__)
> +    genh = QAPIGenH(blurb, __doc__)
> 
> -genc.add(mcgen('''
> +    genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "%(prefix)sqapi-event.h"
> @@ -191,22 +192,26 @@ genc.add(mcgen('''
>  #include "qapi/qmp-event.h"
> 
>  ''',
> -               prefix=prefix))
> +                   prefix=prefix))
> 
> -genh.add(mcgen('''
> +    genh.add(mcgen('''
>  #include "qapi/util.h"
>  #include "%(prefix)sqapi-types.h"
> 
>  ''',
> -               prefix=prefix))
> -
> -schema = QAPISchema(input_file)
> -vis = QAPISchemaGenEventVisitor(prefix)
> -schema.visit(vis)
> -genc.add(vis.defn)
> -genh.add(vis.decl)
> -
> -if do_c:
> -    genc.write(output_dir, prefix + 'qapi-event.c')
> -if do_h:
> -    genh.write(output_dir, prefix + 'qapi-event.h')
> +                   prefix=prefix))
> +
> +    schema = QAPISchema(input_file)
> +    vis = QAPISchemaGenEventVisitor(prefix)
> +    schema.visit(vis)
> +    genc.add(vis.defn)
> +    genh.add(vis.decl)
> +
> +    if do_c:
> +        genc.write(output_dir, prefix + 'qapi-event.c')
> +    if do_h:
> +        genh.write(output_dir, prefix + 'qapi-event.h')
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
> index 2418b80a82..b098b95053 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi-introspect.py
> @@ -167,38 +167,44 @@ const char %(c_name)s[] = %(c_string)s;
>          arg_type = arg_type or self._schema.the_empty_object_type
>          self._gen_json(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
> -opt_unmask = False
> 
> -(input_file, output_dir, do_c, do_h, prefix, opts) = \
> -    parse_command_line('u', ['unmask-non-abi-names'])
> +def main(argv):
> +    # Debugging aid: unmask QAPI schema's type names
> +    # We normally mask them, because they're not QMP wire ABI
> +    opt_unmask = False
> 
> -for o, a in opts:
> -    if o in ('-u', '--unmask-non-abi-names'):
> -        opt_unmask = True
> +    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> +        parse_command_line('u', ['unmask-non-abi-names'])
> 
> -blurb = '''
> +    for o, a in opts:
> +        if o in ('-u', '--unmask-non-abi-names'):
> +            opt_unmask = True
> +
> +    blurb = '''
>   * QAPI/QMP schema introspection
>  '''
> 
> -genc = QAPIGenC(blurb, __doc__)
> -genh = QAPIGenH(blurb, __doc__)
> +    genc = QAPIGenC(blurb, __doc__)
> +    genh = QAPIGenH(blurb, __doc__)
> 
> -genc.add(mcgen('''
> +    genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "%(prefix)sqmp-introspect.h"
> 
>  ''',
> -               prefix=prefix))
> -
> -schema = QAPISchema(input_file)
> -vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
> -schema.visit(vis)
> -genc.add(vis.defn)
> -genh.add(vis.decl)
> -
> -if do_c:
> -    genc.write(output_dir, prefix + 'qmp-introspect.c')
> -if do_h:
> -    genh.write(output_dir, prefix + 'qmp-introspect.h')
> +                   prefix=prefix))
> +
> +    schema = QAPISchema(input_file)
> +    vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
> +    schema.visit(vis)
> +    genc.add(vis.defn)
> +    genh.add(vis.decl)
> +
> +    if do_c:
> +        genc.write(output_dir, prefix + 'qmp-introspect.c')
> +    if do_h:
> +        genh.write(output_dir, prefix + 'qmp-introspect.h')
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> index 5ff2bfcf41..10955d1c01 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi-types.py
> @@ -240,45 +240,51 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          self.decl += gen_object(name, None, [variants.tag_member], variants)
>          self._gen_type_cleanup(name)
> 
> -# If you link code generated from multiple schemata, you want only one
> -# instance of the code for built-in types.  Generate it only when
> -# opt_builtins, enabled by command line option -b.  See also
> -# QAPISchemaGenTypeVisitor.visit_end().
> -opt_builtins = False
> 
> -(input_file, output_dir, do_c, do_h, prefix, opts) = \
> -    parse_command_line('b', ['builtins'])
> +def main(argv):
> +    # If you link code generated from multiple schemata, you want only one
> +    # instance of the code for built-in types.  Generate it only when
> +    # opt_builtins, enabled by command line option -b.  See also
> +    # QAPISchemaGenTypeVisitor.visit_end().
> +    opt_builtins = False
> 
> -for o, a in opts:
> -    if o in ('-b', '--builtins'):
> -        opt_builtins = True
> +    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> +        parse_command_line('b', ['builtins'])
> 
> -blurb = '''
> +    for o, a in opts:
> +        if o in ('-b', '--builtins'):
> +            opt_builtins = True
> +
> +    blurb = '''
>   * Schema-defined QAPI types
>  '''
> 
> -genc = QAPIGenC(blurb, __doc__)
> -genh = QAPIGenH(blurb, __doc__)
> +    genc = QAPIGenC(blurb, __doc__)
> +    genh = QAPIGenH(blurb, __doc__)
> 
> -genc.add(mcgen('''
> +    genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
>  #include "%(prefix)sqapi-types.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -               prefix=prefix))
> +                   prefix=prefix))
> 
> -genh.add(mcgen('''
> +    genh.add(mcgen('''
>  #include "qapi/util.h"
>  '''))
> 
> -schema = QAPISchema(input_file)
> -vis = QAPISchemaGenTypeVisitor(opt_builtins)
> -schema.visit(vis)
> -genc.add(vis.defn)
> -genh.add(vis.decl)
> +    schema = QAPISchema(input_file)
> +    vis = QAPISchemaGenTypeVisitor(opt_builtins)
> +    schema.visit(vis)
> +    genc.add(vis.defn)
> +    genh.add(vis.decl)
> 
> -if do_c:
> -    genc.write(output_dir, prefix + 'qapi-types.c')
> -if do_h:
> -    genh.write(output_dir, prefix + 'qapi-types.h')
> +    if do_c:
> +        genc.write(output_dir, prefix + 'qapi-types.c')
> +    if do_h:
> +        genh.write(output_dir, prefix + 'qapi-types.h')
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 0a1eff7736..6d829c4d1d 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -323,49 +323,55 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          self.decl += gen_visit_decl(name)
>          self.defn += gen_visit_alternate(name, 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
> -# opt_builtins, enabled by command line option -b.  See also
> -# QAPISchemaGenVisitVisitor.visit_end().
> -opt_builtins = False
> 
> -(input_file, output_dir, do_c, do_h, prefix, opts) = \
> -    parse_command_line('b', ['builtins'])
> +def main(argv):
> +    # If you link code generated from multiple schemata, you want only one
> +    # instance of the code for built-in types.  Generate it only when
> +    # opt_builtins, enabled by command line option -b.  See also
> +    # QAPISchemaGenVisitVisitor.visit_end().
> +    opt_builtins = False
> 
> -for o, a in opts:
> -    if o in ('-b', '--builtins'):
> -        opt_builtins = True
> +    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> +        parse_command_line('b', ['builtins'])
> 
> -blurb = '''
> +    for o, a in opts:
> +        if o in ('-b', '--builtins'):
> +            opt_builtins = True
> +
> +    blurb = '''
>   * Schema-defined QAPI visitors
>  '''
> 
> -genc = QAPIGenC(blurb, __doc__)
> -genh = QAPIGenH(blurb, __doc__)
> +    genc = QAPIGenC(blurb, __doc__)
> +    genh = QAPIGenH(blurb, __doc__)
> 
> -genc.add(mcgen('''
> +    genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -               prefix=prefix))
> +                   prefix=prefix))
> 
> -genh.add(mcgen('''
> +    genh.add(mcgen('''
>  #include "qapi/visitor.h"
>  #include "%(prefix)sqapi-types.h"
> 
>  ''',
> -               prefix=prefix))
> -
> -schema = QAPISchema(input_file)
> -vis = QAPISchemaGenVisitVisitor(opt_builtins)
> -schema.visit(vis)
> -genc.add(vis.defn)
> -genh.add(vis.decl)
> -
> -if do_c:
> -    genc.write(output_dir, prefix + 'qapi-visit.c')
> -if do_h:
> -    genh.write(output_dir, prefix + 'qapi-visit.h')
> +                   prefix=prefix))
> +
> +    schema = QAPISchema(input_file)
> +    vis = QAPISchemaGenVisitVisitor(opt_builtins)
> +    schema.visit(vis)
> +    genc.add(vis.defn)
> +    genh.add(vis.decl)
> +
> +    if do_c:
> +        genc.write(output_dir, prefix + 'qapi-visit.c')
> +    if do_h:
> +        genh.write(output_dir, prefix + 'qapi-visit.h')
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
  2018-02-12 19:42   ` Eric Blake
@ 2018-02-18 22:16   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-18 22:16 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:46)
> Whenever qapi-schema.json changes, we run six programs eleven times to
> update eleven files.  Similar for qga/qapi-schema.json.  This is
> silly.  Replace the six programs by a single program that spits out
> all eleven files.
> 
> The programs become modules in new Python package qapi, along with the
> helper library.  This requires moving them to scripts/qapi/.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore                                         |  2 +
>  Makefile                                           | 86 +++++++++----------
>  docs/devel/qapi-code-gen.txt                       | 97 ++++++++++------------
>  monitor.c                                          |  2 +-
>  qapi-schema.json                                   |  2 +-
>  scripts/qapi-gen.py                                | 41 +++++++++
>  scripts/qapi/__init__.py                           |  0
>  scripts/{qapi-commands.py => qapi/commands.py}     | 23 ++---
>  scripts/{qapi.py => qapi/common.py}                | 18 +---
>  scripts/{qapi2texi.py => qapi/doc.py}              | 29 ++-----
>  scripts/{qapi-event.py => qapi/events.py}          | 23 ++---
>  scripts/{qapi-introspect.py => qapi/introspect.py} | 32 ++-----
>  scripts/{qapi-types.py => qapi/types.py}           | 34 ++------
>  scripts/{qapi-visit.py => qapi/visit.py}           | 34 ++------
>  tests/Makefile.include                             | 56 ++++++-------
>  tests/qapi-schema/test-qapi.py                     |  4 +-
>  16 files changed, 193 insertions(+), 290 deletions(-)
>  create mode 100755 scripts/qapi-gen.py
>  create mode 100644 scripts/qapi/__init__.py
>  rename scripts/{qapi-commands.py => qapi/commands.py} (94%)
>  rename scripts/{qapi.py => qapi/common.py} (99%)
>  rename scripts/{qapi2texi.py => qapi/doc.py} (92%)
>  mode change 100755 => 100644
>  rename scripts/{qapi-event.py => qapi/events.py} (92%)
>  rename scripts/{qapi-introspect.py => qapi/introspect.py} (90%)
>  rename scripts/{qapi-types.py => qapi/types.py} (90%)
>  rename scripts/{qapi-visit.py => qapi/visit.py} (92%)
> 
> diff --git a/.gitignore b/.gitignore
> index 704b22285d..2f9a92f6cc 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -28,9 +28,11 @@
>  /linux-headers/asm
>  /qga/qapi-generated
>  /qapi-generated
> +/qapi-gen-timestamp
>  /qapi-types.[ch]
>  /qapi-visit.[ch]
>  /qapi-event.[ch]
> +/qapi-doc.texi
>  /qmp-commands.h
>  /qmp-introspect.[ch]
>  /qmp-marshal.c
> diff --git a/Makefile b/Makefile
> index 4ec7a3cb82..bd781c6aad 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -94,6 +94,7 @@ GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
>  GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
>  GENERATED_FILES += qmp-introspect.h
>  GENERATED_FILES += qmp-introspect.c
> +GENERATED_FILES += qapi-doc.texi
> 
>  GENERATED_FILES += trace/generated-tcg-tracers.h
> 
> @@ -483,25 +484,26 @@ qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated
>  qemu-keymap$(EXESUF): LIBS += $(XKBCOMMON_LIBS)
>  qemu-keymap$(EXESUF): QEMU_CFLAGS += $(XKBCOMMON_CFLAGS)
> 
> -gen-out-type = $(subst .,-,$(suffix $@))
> +qapi-py = $(SRC_PATH)/scripts/qapi/commands.py \
> +$(SRC_PATH)/scripts/qapi/events.py \
> +$(SRC_PATH)/scripts/qapi/introspect.py \
> +$(SRC_PATH)/scripts/qapi/types.py \
> +$(SRC_PATH)/scripts/qapi/visit.py \
> +$(SRC_PATH)/scripts/qapi/common.py \
> +$(SRC_PATH)/scripts/qapi/doc.py \
> +$(SRC_PATH)/scripts/ordereddict.py \
> +$(SRC_PATH)/scripts/qapi-gen.py
> 
> -qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
> -
> -qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
> -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
> -               $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
> -               "GEN","$@")
> -qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
> -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
> -               $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
> -               "GEN","$@")
> -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
> -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
> -               $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
> -               "GEN","$@")
> +qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
> +qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
> +qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \
> +qga/qapi-generated/qga-qapi-doc.texi: \
> +qga/qapi-generated/qapi-gen-timestamp ;
> +qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
> +       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
> +               -o qga/qapi-generated -p "qga-" $<, \
> +               "GEN","$(@:%-timestamp=%)")
> +       @>$@
> 
>  qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
> @@ -518,31 +520,18 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/transaction.json \
>                 $(SRC_PATH)/qapi/ui.json
> 
> -qapi-types.c qapi-types.h :\
> -$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
> -               $(gen-out-type) -o "." -b $<, \
> -               "GEN","$@")
> -qapi-visit.c qapi-visit.h :\
> -$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
> -               $(gen-out-type) -o "." -b $<, \
> -               "GEN","$@")
> -qapi-event.c qapi-event.h :\
> -$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-event.py \
> -               $(gen-out-type) -o "." $<, \
> -               "GEN","$@")
> -qmp-commands.h qmp-marshal.c :\
> -$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
> -               $(gen-out-type) -o "." $<, \
> -               "GEN","$@")
> -qmp-introspect.h qmp-introspect.c :\
> -$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-introspect.py \
> -               $(gen-out-type) -o "." $<, \
> -               "GEN","$@")
> +qapi-types.c qapi-types.h \
> +qapi-visit.c qapi-visit.h \
> +qmp-commands.h qmp-marshal.c \
> +qapi-event.c qapi-event.h \
> +qmp-introspect.h qmp-introspect.c \
> +qapi-doc.texi: \
> +qapi-gen-timestamp ;
> +qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
> +       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
> +               -o "." -b $<, \
> +               "GEN","$(@:%-timestamp=%)")
> +       @>$@
> 
>  QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
>  $(qga-obj-y): $(QGALIB_GEN)
> @@ -602,6 +591,7 @@ clean:
>         rm -f trace/generated-tracers-dtrace.dtrace*
>         rm -f trace/generated-tracers-dtrace.h*
>         rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
> +       rm -f qapi-gen-timestamp
>         rm -rf qapi-generated
>         rm -rf qga/qapi-generated
>         for d in $(ALL_SUBDIRS); do \
> @@ -810,13 +800,11 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt
>  qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
>         $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
> 
> -docs/interop/qemu-qmp-qapi.texi docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
> +docs/interop/qemu-qmp-qapi.texi: qapi-doc.texi
> +       @cp -p $< $@
> 
> -docs/interop/qemu-qmp-qapi.texi: $(qapi-modules)
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
> -
> -docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json
> -       $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
> +docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi
> +       @cp -p $< $@
> 
>  qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
>  qemu.1: qemu-option-trace.texi
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index 5900b39b91..1a1cbaea7b 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -899,12 +899,13 @@ the names of built-in types.  Clients should examine member
> 
>  == Code generation ==
> 
> -Schemas are fed into five scripts to generate all the code/files that,
> -paired with the core QAPI libraries, comprise everything required to
> -take JSON commands read in by a Client JSON Protocol server, unmarshal
> -the arguments into the underlying C types, call into the corresponding
> -C function, map the response back to a Client JSON Protocol response
> -to be returned to the user, and introspect the commands.
> +The QAPI code generator qapi-gen.py generates code and documentation
> +from the schema.  Together with the core QAPI libraries, this code
> +provides everything required to take JSON commands read in by a Client
> +JSON Protocol server, unmarshal the arguments into the underlying C
> +types, call into the corresponding C function, map the response back
> +to a Client JSON Protocol response to be returned to the user, and
> +introspect the commands.
> 
>  As an example, we'll use the following schema, which describes a
>  single complex user-defined type, along with command which takes a
> @@ -922,18 +923,23 @@ qmp_my_command(); everything else is produced by the generator.
> 
>      { 'event': 'MY_EVENT' }
> 
> +We run qapi-gen.py like this:
> +
> +    $ python scripts/qapi-gen.py --output-dir="qapi-generated" \
> +    --prefix="example-" example-schema.json
> +
>  For a more thorough look at generated code, the testsuite includes
>  tests/qapi-schema/qapi-schema-tests.json that covers more examples of
>  what the generator will accept, and compiles the resulting C code as
>  part of 'make check-unit'.
> 
> -=== scripts/qapi-types.py ===
> +=== Code generated for QAPI types ===
> 
> -Used to generate the C types defined by a schema, along with
> -supporting code. The following files are created:
> +The following files are created:
> 
>  $(prefix)qapi-types.h - C types corresponding to types defined in
> -                        the schema you pass in
> +                        the schema
> +
>  $(prefix)qapi-types.c - Cleanup functions for the above C types
> 
>  The $(prefix) is an optional parameter used as a namespace to keep the
> @@ -943,8 +949,6 @@ created code.
> 
>  Example:
> 
> -    $ python scripts/qapi-types.py --output-dir="qapi-generated" \
> -    --prefix="example-" example-schema.json
>      $ cat qapi-generated/example-qapi-types.h
>  [Uninteresting stuff omitted...]
> 
> @@ -1008,28 +1012,26 @@ Example:
>          visit_free(v);
>      }
> 
> -=== scripts/qapi-visit.py ===
> +=== Code generated for visiting QAPI types ===
> 
> -Used to generate the visitor functions used to walk through and
> -convert between a native QAPI C data structure and some other format
> -(such as QObject); the generated functions are named visit_type_FOO()
> -and visit_type_FOO_members().
> +These are the visitor functions used to walk through and convert
> +between a native QAPI C data structure and some other format (such as
> +QObject); the generated functions are named visit_type_FOO() and
> +visit_type_FOO_members().
> 
>  The following files are generated:
> 
> -$(prefix)qapi-visit.c: visitor function for a particular C type, used
> +$(prefix)qapi-visit.c: Visitor function for a particular C type, used
>                         to automagically convert QObjects into the
>                         corresponding C type and vice-versa, as well
>                         as for deallocating memory for an existing C
>                         type
> 
> -$(prefix)qapi-visit.h: declarations for previously mentioned visitor
> +$(prefix)qapi-visit.h: Declarations for previously mentioned visitor
>                         functions
> 
>  Example:
> 
> -    $ python scripts/qapi-visit.py --output-dir="qapi-generated"
> -    --prefix="example-" example-schema.json
>      $ cat qapi-generated/example-qapi-visit.h
>  [Uninteresting stuff omitted...]
> 
> @@ -1137,30 +1139,22 @@ Example:
>          error_propagate(errp, err);
>      }
> 
> -=== scripts/qapi-commands.py ===
> +=== Code generated for commands ===
> 
> -Used to generate the marshaling/dispatch functions for the commands
> -defined in the schema. The generated code implements
> -qmp_marshal_COMMAND() (registered automatically), and declares
> -qmp_COMMAND() that the user must implement.  The following files are
> -generated:
> +These are the marshaling/dispatch functions for the commands defined
> +in the schema.  The generated code provides qmp_marshal_COMMAND(), and
> +declares qmp_COMMAND() that the user must implement.
> 
> -$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
> -                        QMP command defined in the schema. Functions
> -                        generated by qapi-visit.py are used to
> -                        convert QObjects received from the wire into
> -                        function parameters, and uses the same
> -                        visitor functions to convert native C return
> -                        values to QObjects from transmission back
> -                        over the wire.
> +The following files are generated:
> +
> +$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each
> +                        QMP command defined in the schema
> 
>  $(prefix)qmp-commands.h: Function prototypes for the QMP commands
> -                         specified in the schema.
> +                         specified in the schema
> 
>  Example:
> 
> -    $ python scripts/qapi-commands.py --output-dir="qapi-generated"
> -    --prefix="example-" example-schema.json
>      $ cat qapi-generated/example-qmp-commands.h
>  [Uninteresting stuff omitted...]
> 
> @@ -1242,20 +1236,20 @@ Example:
>                               qmp_marshal_my_command, QCO_NO_OPTIONS);
>      }
> 
> -=== scripts/qapi-event.py ===
> +=== Code generated for events ===
> 
> -Used to generate the event-related C code defined by a schema, with
> -implementations for qapi_event_send_FOO(). The following files are
> -created:
> +This is the code related to events defined in the schema, providing
> +qapi_event_send_EVENT().
> +
> +The following files are created:
> 
>  $(prefix)qapi-event.h - Function prototypes for each event type, plus an
>                          enumeration of all event names
> +
>  $(prefix)qapi-event.c - Implementation of functions to send an event
> 
>  Example:
> 
> -    $ python scripts/qapi-event.py --output-dir="qapi-generated"
> -    --prefix="example-" example-schema.json
>      $ cat qapi-generated/example-qapi-event.h
>  [Uninteresting stuff omitted...]
> 
> @@ -1302,23 +1296,22 @@ Example:
>      }
> 
>      const char *const example_QAPIEvent_lookup[] = {
> -        [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
> +
> +[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>          [EXAMPLE_QAPI_EVENT__MAX] = NULL,
>      };
> 
> -=== scripts/qapi-introspect.py ===
> +=== Code generated for introspection ===
> 
> -Used to generate the introspection C code for a schema. The following
> -files are created:
> +The following files are created:
> 
>  $(prefix)qmp-introspect.c - Defines a string holding a JSON
> -                            description of the schema.
> -$(prefix)qmp-introspect.h - Declares the above string.
> +                            description of the schema
> +
> +$(prefix)qmp-introspect.h - Declares the above string
> 
>  Example:
> 
> -    $ python scripts/qapi-introspect.py --output-dir="qapi-generated"
> -    --prefix="example-" example-schema.json
>      $ cat qapi-generated/example-qmp-introspect.h
>  [Uninteresting stuff omitted...]
> 
> diff --git a/monitor.c b/monitor.c
> index f4992505b1..df670f3e15 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -951,7 +951,7 @@ EventInfoList *qmp_query_events(Error **errp)
>   * visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it
>   * to QObject with generated output marshallers, every time.  Instead,
>   * we do it in test-qobject-input-visitor.c, just to make sure
> - * qapi-introspect.py's output actually conforms to the schema.
> + * qapi-gen.py's output actually conforms to the schema.
>   */
>  static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
>                                   Error **errp)
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 5c06745c79..0d651c8399 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -72,7 +72,7 @@
>          'q_obj_CpuInfo-base'    # CPU, visible through query-cpu
>      ] } }
> 
> -# Documentation generated with qapi2texi.py is in source order, with
> +# Documentation generated with qapi-gen.py is in source order, with
>  # included sub-schemas inserted at the first include directive
>  # (subsequent include directives have no effect).  To get a sane and
>  # stable order, it's best to include each sub-schema just once, or
> diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
> new file mode 100755
> index 0000000000..2100ca1145
> --- /dev/null
> +++ b/scripts/qapi-gen.py
> @@ -0,0 +1,41 @@
> +#!/usr/bin/env python
> +# QAPI generator
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2 or later.
> +# See the COPYING file in the top-level directory.
> +
> +import sys
> +from qapi.common import parse_command_line, QAPISchema
> +from qapi.types import gen_types
> +from qapi.visit import gen_visit
> +from qapi.commands import gen_commands
> +from qapi.events import gen_events
> +from qapi.introspect import gen_introspect
> +from qapi.doc import gen_doc
> +
> +
> +def main(argv):
> +    (input_file, output_dir, prefix, opts) = \
> +        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
> +
> +    opt_builtins = False
> +    opt_unmask = False
> +
> +    for o, a in opts:
> +        if o in ('-b', '--builtins'):
> +            opt_builtins = True
> +        if o in ('-u', '--unmask-non-abi-names'):
> +            opt_unmask = True
> +
> +    schema = QAPISchema(input_file)
> +
> +    gen_types(schema, output_dir, prefix, opt_builtins)
> +    gen_visit(schema, output_dir, prefix, opt_builtins)
> +    gen_commands(schema, output_dir, prefix)
> +    gen_events(schema, output_dir, prefix)
> +    gen_introspect(schema, output_dir, prefix, opt_unmask)
> +    gen_doc(schema, output_dir, prefix)
> +
> +
> +if __name__ == '__main__':
> +    main(sys.argv)
> diff --git a/scripts/qapi/__init__.py b/scripts/qapi/__init__.py
> new file mode 100644
> index 0000000000..e69de29bb2
> diff --git a/scripts/qapi-commands.py b/scripts/qapi/commands.py
> similarity index 94%
> rename from scripts/qapi-commands.py
> rename to scripts/qapi/commands.py
> index 8584cb5873..a744611d58 100644
> --- a/scripts/qapi-commands.py
> +++ b/scripts/qapi/commands.py
> @@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>  See the COPYING file in the top-level directory.
>  """
> 
> -from qapi import *
> +from qapi.common import *
> 
> 
>  def gen_command_decl(name, arg_type, boxed, ret_type):
> @@ -255,13 +255,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>          self._regy += gen_register_command(name, success_response)
> 
> 
> -def main(argv):
> -    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
> -
> -    blurb = '''
> - * Schema-defined QAPI/QMP commands
> -'''
> -
> +def gen_commands(schema, output_dir, prefix):
> +    blurb = ' * Schema-defined QAPI/QMP commands'
>      genc = QAPIGenC(blurb, __doc__)
>      genh = QAPIGenH(blurb, __doc__)
> 
> @@ -290,17 +285,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>  ''',
>                     prefix=prefix, c_prefix=c_name(prefix, protect=False)))
> 
> -    schema = QAPISchema(input_file)
>      vis = QAPISchemaGenCommandVisitor(prefix)
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -
> -    if do_c:
> -        genc.write(output_dir, prefix + 'qmp-marshal.c')
> -    if do_h:
> -        genh.write(output_dir, prefix + 'qmp-commands.h')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +    genc.write(output_dir, prefix + 'qmp-marshal.c')
> +    genh.write(output_dir, prefix + 'qmp-commands.h')
> diff --git a/scripts/qapi.py b/scripts/qapi/common.py
> similarity index 99%
> rename from scripts/qapi.py
> rename to scripts/qapi/common.py
> index 9693fd1851..868ec25deb 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi/common.py
> @@ -1932,17 +1932,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
> 
>      try:
>          opts, args = getopt.gnu_getopt(sys.argv[1:],
> -                                       'chp:o:' + extra_options,
> -                                       ['source', 'header', 'prefix=',
> -                                        'output-dir='] + extra_long_options)
> +                                       'p:o:' + extra_options,
> +                                       ['prefix=', 'output-dir=']
> +                                       + extra_long_options)
>      except getopt.GetoptError as err:
>          print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
>          sys.exit(1)
> 
>      output_dir = ''
>      prefix = ''
> -    do_c = False
> -    do_h = False
>      extra_opts = []
> 
>      for oa in opts:
> @@ -1956,23 +1954,15 @@ def parse_command_line(extra_options='', extra_long_options=[]):
>              prefix = a
>          elif o in ('-o', '--output-dir'):
>              output_dir = a + '/'
> -        elif o in ('-c', '--source'):
> -            do_c = True
> -        elif o in ('-h', '--header'):
> -            do_h = True
>          else:
>              extra_opts.append(oa)
> 
> -    if not do_c and not do_h:
> -        do_c = True
> -        do_h = True
> -
>      if len(args) != 1:
>          print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
>          sys.exit(1)
>      fname = args[0]
> 
> -    return (fname, output_dir, do_c, do_h, prefix, extra_opts)
> +    return (fname, output_dir, prefix, extra_opts)
> 
> 
>  #
> diff --git a/scripts/qapi2texi.py b/scripts/qapi/doc.py
> old mode 100755
> new mode 100644
> similarity index 92%
> rename from scripts/qapi2texi.py
> rename to scripts/qapi/doc.py
> index 8a604d86a6..cc4d5a43fb
> --- a/scripts/qapi2texi.py
> +++ b/scripts/qapi/doc.py
> @@ -4,11 +4,10 @@
>  # This work is licensed under the terms of the GNU LGPL, version 2+.
>  # See the COPYING file in the top-level directory.
>  """This script produces the documentation of a qapi schema in texinfo format"""
> +
>  from __future__ import print_function
>  import re
> -import sys
> -
> -import qapi
> +import qapi.common
> 
>  MSG_FMT = """
>  @deftypefn {type} {{}} {name}
> @@ -197,7 +196,7 @@ def texi_entity(doc, what, base=None, variants=None,
>              + texi_sections(doc))
> 
> 
> -class QAPISchemaGenDocVisitor(qapi.QAPISchemaVisitor):
> +class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
>      def __init__(self):
>          self.out = None
>          self.cur_doc = None
> @@ -272,20 +271,8 @@ def texi_schema(schema):
>      return gen.out
> 
> 
> -def main(argv):
> -    """Takes schema argument, prints result to stdout"""
> -    if len(argv) != 2:
> -        print("%s: need exactly 1 argument: SCHEMA" % argv[0], file=sys.stderr)
> -        sys.exit(1)
> -
> -    schema = qapi.QAPISchema(argv[1])
> -    if not qapi.doc_required:
> -        print("%s: need pragma 'doc-required' "
> -               "to generate documentation" % argv[0], file=sys.stderr)
> -        sys.exit(1)
> -    print('@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n')
> -    print(texi_schema(schema), end='')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +def gen_doc(schema, output_dir, prefix):
> +    if qapi.common.doc_required:
> +        gen = qapi.common.QAPIGenDoc()
> +        gen.add(texi_schema(schema))
> +        gen.write(output_dir, prefix + 'qapi-doc.texi')
> diff --git a/scripts/qapi-event.py b/scripts/qapi/events.py
> similarity index 92%
> rename from scripts/qapi-event.py
> rename to scripts/qapi/events.py
> index e7e07f0055..b7dc82004f 100644
> --- a/scripts/qapi-event.py
> +++ b/scripts/qapi/events.py
> @@ -12,7 +12,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>  See the COPYING file in the top-level directory.
>  """
> 
> -from qapi import *
> +from qapi.common import *
> 
> 
>  def build_event_send_proto(name, arg_type, boxed):
> @@ -171,13 +171,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
>          self._event_names.append(name)
> 
> 
> -def main(argv):
> -    (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
> -
> -    blurb = '''
> - * Schema-defined QAPI/QMP events
> -'''
> -
> +def gen_events(schema, output_dir, prefix):
> +    blurb = ' * Schema-defined QAPI/QMP events'
>      genc = QAPIGenC(blurb, __doc__)
>      genh = QAPIGenH(blurb, __doc__)
> 
> @@ -201,17 +196,9 @@ def main(argv):
>  ''',
>                     prefix=prefix))
> 
> -    schema = QAPISchema(input_file)
>      vis = QAPISchemaGenEventVisitor(prefix)
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -
> -    if do_c:
> -        genc.write(output_dir, prefix + 'qapi-event.c')
> -    if do_h:
> -        genh.write(output_dir, prefix + 'qapi-event.h')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +    genc.write(output_dir, prefix + 'qapi-event.c')
> +    genh.write(output_dir, prefix + 'qapi-event.h')
> diff --git a/scripts/qapi-introspect.py b/scripts/qapi/introspect.py
> similarity index 90%
> rename from scripts/qapi-introspect.py
> rename to scripts/qapi/introspect.py
> index b098b95053..1e4f065164 100644
> --- a/scripts/qapi-introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -10,7 +10,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>  See the COPYING file in the top-level directory.
>  """
> 
> -from qapi import *
> +from qapi.common import *
> 
> 
>  # Caveman's json.dumps() replacement (we're stuck at Python 2.4)
> @@ -168,22 +168,8 @@ const char %(c_name)s[] = %(c_string)s;
>          self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
> 
> 
> -def main(argv):
> -    # Debugging aid: unmask QAPI schema's type names
> -    # We normally mask them, because they're not QMP wire ABI
> -    opt_unmask = False
> -
> -    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> -        parse_command_line('u', ['unmask-non-abi-names'])
> -
> -    for o, a in opts:
> -        if o in ('-u', '--unmask-non-abi-names'):
> -            opt_unmask = True
> -
> -    blurb = '''
> - * QAPI/QMP schema introspection
> -'''
> -
> +def gen_introspect(schema, output_dir, prefix, opt_unmask):
> +    blurb = ' * QAPI/QMP schema introspection'
>      genc = QAPIGenC(blurb, __doc__)
>      genh = QAPIGenH(blurb, __doc__)
> 
> @@ -194,17 +180,9 @@ def main(argv):
>  ''',
>                     prefix=prefix))
> 
> -    schema = QAPISchema(input_file)
>      vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask)
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -
> -    if do_c:
> -        genc.write(output_dir, prefix + 'qmp-introspect.c')
> -    if do_h:
> -        genh.write(output_dir, prefix + 'qmp-introspect.h')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +    genc.write(output_dir, prefix + 'qmp-introspect.c')
> +    genh.write(output_dir, prefix + 'qmp-introspect.h')
> diff --git a/scripts/qapi-types.py b/scripts/qapi/types.py
> similarity index 90%
> rename from scripts/qapi-types.py
> rename to scripts/qapi/types.py
> index 10955d1c01..aa3c01e750 100644
> --- a/scripts/qapi-types.py
> +++ b/scripts/qapi/types.py
> @@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>  # See the COPYING file in the top-level directory.
>  """
> 
> -from qapi import *
> +from qapi.common import *
> 
> 
>  # variants must be emitted before their container; track what has already
> @@ -241,24 +241,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>          self._gen_type_cleanup(name)
> 
> 
> -def main(argv):
> -    # If you link code generated from multiple schemata, you want only one
> -    # instance of the code for built-in types.  Generate it only when
> -    # opt_builtins, enabled by command line option -b.  See also
> -    # QAPISchemaGenTypeVisitor.visit_end().
> -    opt_builtins = False
> -
> -    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> -        parse_command_line('b', ['builtins'])
> -
> -    for o, a in opts:
> -        if o in ('-b', '--builtins'):
> -            opt_builtins = True
> -
> -    blurb = '''
> - * Schema-defined QAPI types
> -'''
> -
> +def gen_types(schema, output_dir, prefix, opt_builtins):
> +    blurb = ' * Schema-defined QAPI types'
>      genc = QAPIGenC(blurb, __doc__)
>      genh = QAPIGenH(blurb, __doc__)
> 
> @@ -274,17 +258,9 @@ def main(argv):
>  #include "qapi/util.h"
>  '''))
> 
> -    schema = QAPISchema(input_file)
>      vis = QAPISchemaGenTypeVisitor(opt_builtins)
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -
> -    if do_c:
> -        genc.write(output_dir, prefix + 'qapi-types.c')
> -    if do_h:
> -        genh.write(output_dir, prefix + 'qapi-types.h')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +    genc.write(output_dir, prefix + 'qapi-types.c')
> +    genh.write(output_dir, prefix + 'qapi-types.h')
> diff --git a/scripts/qapi-visit.py b/scripts/qapi/visit.py
> similarity index 92%
> rename from scripts/qapi-visit.py
> rename to scripts/qapi/visit.py
> index 6d829c4d1d..f966e7975f 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi/visit.py
> @@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>  See the COPYING file in the top-level directory.
>  """
> 
> -from qapi import *
> +from qapi.common import *
> 
> 
>  def gen_visit_decl(name, scalar=False):
> @@ -324,24 +324,8 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>          self.defn += gen_visit_alternate(name, variants)
> 
> 
> -def main(argv):
> -    # If you link code generated from multiple schemata, you want only one
> -    # instance of the code for built-in types.  Generate it only when
> -    # opt_builtins, enabled by command line option -b.  See also
> -    # QAPISchemaGenVisitVisitor.visit_end().
> -    opt_builtins = False
> -
> -    (input_file, output_dir, do_c, do_h, prefix, opts) = \
> -        parse_command_line('b', ['builtins'])
> -
> -    for o, a in opts:
> -        if o in ('-b', '--builtins'):
> -            opt_builtins = True
> -
> -    blurb = '''
> - * Schema-defined QAPI visitors
> -'''
> -
> +def gen_visit(schema, output_dir, prefix, opt_builtins):
> +    blurb = ' * Schema-defined QAPI visitors'
>      genc = QAPIGenC(blurb, __doc__)
>      genh = QAPIGenH(blurb, __doc__)
> 
> @@ -361,17 +345,9 @@ def main(argv):
>  ''',
>                     prefix=prefix))
> 
> -    schema = QAPISchema(input_file)
>      vis = QAPISchemaGenVisitVisitor(opt_builtins)
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -
> -    if do_c:
> -        genc.write(output_dir, prefix + 'qapi-visit.c')
> -    if do_h:
> -        genh.write(output_dir, prefix + 'qapi-visit.h')
> -
> -
> -if __name__ == '__main__':
> -    main(sys.argv)
> +    genc.write(output_dir, prefix + 'qapi-visit.c')
> +    genh.write(output_dir, prefix + 'qapi-visit.h')
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index f41da235ae..b406531b34 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -23,7 +23,16 @@ check-help:
>  ifneq ($(wildcard config-host.mak),)
>  export SRC_PATH
> 
> -qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
> +# TODO don't duplicate $(SRC_PATH)/Makefile's qapi-py here
> +qapi-py = $(SRC_PATH)/scripts/qapi/commands.py \
> +$(SRC_PATH)/scripts/qapi/events.py \
> +$(SRC_PATH)/scripts/qapi/introspect.py \
> +$(SRC_PATH)/scripts/qapi/types.py \
> +$(SRC_PATH)/scripts/qapi/visit.py \
> +$(SRC_PATH)/scripts/qapi/common.py \
> +$(SRC_PATH)/scripts/qapi/doc.py \
> +$(SRC_PATH)/scripts/ordereddict.py \
> +$(SRC_PATH)/scripts/qapi-gen.py
> 
>  # Get the list of all supported sysemu targets
>  SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
> @@ -645,34 +654,24 @@ tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
>  tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
>         $(test-block-obj-y)
> 
> -tests/test-qapi-types.c tests/test-qapi-types.h :\
> -$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
> -               $(gen-out-type) -o tests -p "test-" $<, \
> -               "GEN","$@")
> -tests/test-qapi-visit.c tests/test-qapi-visit.h :\
> -$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
> -               $(gen-out-type) -o tests -p "test-" $<, \
> -               "GEN","$@")
> -tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
> -$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
> -               $(gen-out-type) -o tests -p "test-" $<, \
> -               "GEN","$@")
> -tests/test-qapi-event.c tests/test-qapi-event.h :\
> -$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
> -               $(gen-out-type) -o tests -p "test-" $<, \
> -               "GEN","$@")
> -tests/test-qmp-introspect.c tests/test-qmp-introspect.h :\
> -$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
> -               $(gen-out-type) -o tests -p "test-" $<, \
> -               "GEN","$@")
> +tests/test-qapi-types.c tests/test-qapi-types.h \
> +tests/test-qapi-visit.c tests/test-qapi-visit.h \
> +tests/test-qmp-commands.h tests/test-qmp-marshal.c \
> +tests/test-qapi-event.c tests/test-qapi-event.h \
> +tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
> +tests/test-qapi-gen-timestamp ;
> +tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
> +       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
> +               -o tests -p "test-" $<, \
> +               "GEN","$(@:%-timestamp=%)")
> +       @>$@
> 
> -tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
> -       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
> +tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(qapi-py)
> +       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
> +               -o tests/qapi-schema -p "doc-good-" $<, \
> +               "GEN","$@")
> +       @mv tests/qapi-schema/doc-good-qapi-doc.texi $@
> +       @rm -f tests/qapi-schema/doc-good-qapi-*.[ch] tests/qapi-schema/doc-good-qmp-*.[ch]
> 
>  tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
>  tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
> @@ -941,6 +940,7 @@ check-clean:
>         $(MAKE) -C tests/tcg clean
>         rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
>         rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))
> +       rm -f tests/test-qapi-gen-timestamp
> 
>  clean: check-clean
> 
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index ac43d3458e..bb1b6dd297 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -11,10 +11,8 @@
>  #
> 
>  from __future__ import print_function
> -from qapi import *
> -from pprint import pprint
> -import os
>  import sys
> +from qapi.common import QAPISchema, QAPISchemaVisitor
> 
> 
>  class QAPISchemaTestVisitor(QAPISchemaVisitor):
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
  2018-02-12 19:44   ` Eric Blake
  2018-02-13 15:24   ` Marc-Andre Lureau
@ 2018-02-18 22:31   ` Michael Roth
  2018-02-23 17:21     ` Markus Armbruster
  2 siblings, 1 reply; 110+ messages in thread
From: Michael Roth @ 2018-02-18 22:31 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:47)
> argparse is nicer to use than getopt, and gives us --help almost for
> free.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  scripts/qapi-gen.py    | 48 ++++++++++++++++++++++++++++++------------------
>  scripts/qapi/common.py | 43 -------------------------------------------
>  2 files changed, 30 insertions(+), 61 deletions(-)
> 
> diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
> index 2100ca1145..e5be484e3e 100755
> --- a/scripts/qapi-gen.py
> +++ b/scripts/qapi-gen.py
> @@ -4,8 +4,11 @@
>  # This work is licensed under the terms of the GNU GPL, version 2 or later.
>  # See the COPYING file in the top-level directory.
> 
> +from __future__ import print_function
> +import argparse
> +import re
>  import sys
> -from qapi.common import parse_command_line, QAPISchema
> +from qapi.common import QAPISchema
>  from qapi.types import gen_types
>  from qapi.visit import gen_visit
>  from qapi.commands import gen_commands
> @@ -15,26 +18,35 @@ from qapi.doc import gen_doc
> 
> 
>  def main(argv):
> -    (input_file, output_dir, prefix, opts) = \
> -        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
> +    parser = argparse.ArgumentParser(
> +        description='Generate code from a QAPI schema')
> +    parser.add_argument('-b', '--builtins', action='store_true',
> +                        help="generate code for built-in types")
> +    parser.add_argument('-o', '--output_dir', action='store', default='',

Was the change from --output-dir to --output_dir intentional? The former
seems more consistent.

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

* Re: [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
  2018-02-12 19:48   ` Eric Blake
@ 2018-02-18 22:43   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-18 22:43 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:48)
> A massive number of objects depends on QAPI-generated headers.  In my
> "build everything" tree, it's roughly 4800 out of 5100.  This is
> particularly annoying when only some of the generated files change,
> say for a doc fix.
> 
> Improve qapi-gen.py to touch its output files only if they actually
> change.  Rebuild time for a QAPI doc fix drops from many minutes to a
> few seconds.  Rebuilds get faster for certain code changes, too.  For
> instance, adding a simple QMP event now recompiles less than 200
> instead of 4800 objects.  But adding a QAPI type is as bad as ever;
> we've clearly got more work to do.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi/common.py | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 8290795dc1..2e58573a39 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1951,9 +1951,16 @@ class QAPIGen(object):
>              except os.error as e:
>                  if e.errno != errno.EEXIST:
>                      raise
> -        f = open(os.path.join(output_dir, fname), 'w')
> -        f.write(self._top(fname) + self._preamble + self._body
> +        fd = os.open(os.path.join(output_dir, fname),
> +                     os.O_RDWR | os.O_CREAT, 0666)
> +        f = os.fdopen(fd, 'r+')
> +        text = (self._top(fname) + self._preamble + self._body
>                  + self._bottom(fname))
> +        oldtext = f.read(len(text) + 1)
> +        if text != oldtext:
> +            f.seek(0)
> +            f.truncate(0)
> +            f.write(text)
>          f.close()
> 
> 
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages Markus Armbruster
@ 2018-02-18 23:11   ` Michael Roth
  0 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-18 23:11 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:49)
> Error messages print absolute file names of included files even if the
> user gave a relative one on the command line:
> 
>     $ PYTHONPATH=scripts python -B tests/qapi-schema/test-qapi.py tests/qapi-schema/include-cycle.json
>     In file included from tests/qapi-schema/include-cycle.json:1:
>     In file included from /work/armbru/qemu/tests/qapi-schema/include-cycle-b.json:1:
>     /work/armbru/qemu/tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json
> 
> Improve this to
> 
>     In file included from tests/qapi-schema/include-cycle.json:1:
>     In file included from tests/qapi-schema/include-cycle-b.json:1:
>     tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json
> 
> The error message when an include file can't be opened prints the
> include directive's file name, which is relative to the including
> file.  Change this to print the file name relative to the working
> directory.  Visible in tests/qapi-schema/include-no-file.err.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi/common.py                | 12 ++++++------
>  tests/qapi-schema/include-no-file.err |  2 +-
>  2 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 2e58573a39..3e92b38ade 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -259,9 +259,8 @@ class QAPIDoc(object):
>  class QAPISchemaParser(object):
> 
>      def __init__(self, fp, previously_included=[], incl_info=None):
> -        abs_fname = os.path.abspath(fp.name)
>          self.fname = fp.name
> -        previously_included.append(abs_fname)
> +        previously_included.append(os.path.abspath(fp.name))
>          self.incl_info = incl_info
>          self.src = fp.read()
>          if self.src == '' or self.src[-1] != '\n':
> @@ -292,7 +291,7 @@ class QAPISchemaParser(object):
>                  if not isinstance(include, str):
>                      raise QAPISemError(info,
>                                         "Value of 'include' must be a string")
> -                self._include(include, info, os.path.dirname(abs_fname),
> +                self._include(include, info, os.path.dirname(self.fname),
>                                previously_included)
>              elif "pragma" in expr:
>                  self.reject_expr_doc(cur_doc)
> @@ -325,7 +324,8 @@ class QAPISchemaParser(object):
>                  % doc.symbol)
> 
>      def _include(self, include, info, base_dir, previously_included):
> -        incl_abs_fname = os.path.join(base_dir, include)
> +        incl_fname = os.path.join(base_dir, include)
> +        incl_abs_fname = os.path.abspath(incl_fname)
>          # catch inclusion cycle
>          inf = info
>          while inf:
> @@ -337,9 +337,9 @@ class QAPISchemaParser(object):
>          if incl_abs_fname in previously_included:
>              return
>          try:
> -            fobj = open(incl_abs_fname, 'r')
> +            fobj = open(incl_fname, 'r')
>          except IOError as e:
> -            raise QAPISemError(info, '%s: %s' % (e.strerror, include))
> +            raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
>          exprs_include = QAPISchemaParser(fobj, previously_included, info)
>          self.exprs.extend(exprs_include.exprs)
>          self.docs.extend(exprs_include.docs)
> diff --git a/tests/qapi-schema/include-no-file.err b/tests/qapi-schema/include-no-file.err
> index d5b9b22d85..e42bcf4bc1 100644
> --- a/tests/qapi-schema/include-no-file.err
> +++ b/tests/qapi-schema/include-no-file.err
> @@ -1 +1 @@
> -tests/qapi-schema/include-no-file.json:1: No such file or directory: include-no-file-sub.json
> +tests/qapi-schema/include-no-file.json:1: No such file or directory: tests/qapi-schema/include-no-file-sub.json
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs Markus Armbruster
@ 2018-02-18 23:13   ` Michael Roth
  0 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-18 23:13 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:50)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi/common.py | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 3e92b38ade..d72c339ad5 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1461,13 +1461,13 @@ class QAPISchema(object):
>      def __init__(self, fname):
>          try:
>              parser = QAPISchemaParser(open(fname, 'r'))
> -            self.exprs = check_exprs(parser.exprs)
> +            exprs = check_exprs(parser.exprs)
>              self.docs = parser.docs
>              self._entity_dict = {}
>              self._predefining = True
>              self._def_predefineds()
>              self._predefining = False
> -            self._def_exprs()
> +            self._def_exprs(exprs)
>              self.check()
>          except QAPIError as err:
>              print(err, file=sys.stderr)
> @@ -1652,8 +1652,8 @@ class QAPISchema(object):
>                  name, info, doc, 'arg', self._make_members(data, info))
>          self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed))
> 
> -    def _def_exprs(self):
> -        for expr_elem in self.exprs:
> +    def _def_exprs(self, exprs):
> +        for expr_elem in exprs:
>              expr = expr_elem['expr']
>              info = expr_elem['info']
>              doc = expr_elem.get('doc')
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
  2018-02-12 19:52   ` Eric Blake
@ 2018-02-18 23:17   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-18 23:17 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:51)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi-gen.py            |  8 ++++++--
>  scripts/qapi/common.py         | 23 +++++++++--------------
>  tests/qapi-schema/test-qapi.py | 10 ++++++++--
>  3 files changed, 23 insertions(+), 18 deletions(-)
> 
> diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
> index e5be484e3e..fea7d4589b 100755
> --- a/scripts/qapi-gen.py
> +++ b/scripts/qapi-gen.py
> @@ -8,7 +8,7 @@ from __future__ import print_function
>  import argparse
>  import re
>  import sys
> -from qapi.common import QAPISchema
> +from qapi.common import QAPIError, QAPISchema
>  from qapi.types import gen_types
>  from qapi.visit import gen_visit
>  from qapi.commands import gen_commands
> @@ -39,7 +39,11 @@ def main(argv):
>                file=sys.stderr)
>          sys.exit(1)
> 
> -    schema = QAPISchema(args.schema)
> +    try:
> +        schema = QAPISchema(args.schema)
> +    except QAPIError as err:
> +        print(err, file=sys.stderr)
> +        exit(1)
> 
>      gen_types(schema, args.output_dir, args.prefix, args.builtins)
>      gen_visit(schema, args.output_dir, args.prefix, args.builtins)
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index d72c339ad5..dce289ae21 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -16,7 +16,6 @@ import errno
>  import os
>  import re
>  import string
> -import sys
>  try:
>      from collections import OrderedDict
>  except:
> @@ -1459,19 +1458,15 @@ class QAPISchemaEvent(QAPISchemaEntity):
> 
>  class QAPISchema(object):
>      def __init__(self, fname):
> -        try:
> -            parser = QAPISchemaParser(open(fname, 'r'))
> -            exprs = check_exprs(parser.exprs)
> -            self.docs = parser.docs
> -            self._entity_dict = {}
> -            self._predefining = True
> -            self._def_predefineds()
> -            self._predefining = False
> -            self._def_exprs(exprs)
> -            self.check()
> -        except QAPIError as err:
> -            print(err, file=sys.stderr)
> -            exit(1)
> +        parser = QAPISchemaParser(open(fname, 'r'))
> +        exprs = check_exprs(parser.exprs)
> +        self.docs = parser.docs
> +        self._entity_dict = {}
> +        self._predefining = True
> +        self._def_predefineds()
> +        self._predefining = False
> +        self._def_exprs(exprs)
> +        self.check()
> 
>      def _def_entity(self, ent):
>          # Only the predefined types are allowed to not have info
> diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
> index bb1b6dd297..4da14b43af 100644
> --- a/tests/qapi-schema/test-qapi.py
> +++ b/tests/qapi-schema/test-qapi.py
> @@ -12,7 +12,7 @@
> 
>  from __future__ import print_function
>  import sys
> -from qapi.common import QAPISchema, QAPISchemaVisitor
> +from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
> 
> 
>  class QAPISchemaTestVisitor(QAPISchemaVisitor):
> @@ -52,7 +52,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
>              for v in variants.variants:
>                  print('    case %s: %s' % (v.name, v.type.name))
> 
> -schema = QAPISchema(sys.argv[1])
> +
> +try:
> +    schema = QAPISchema(sys.argv[1])
> +except QAPIError as err:
> +    print(err, file=sys.stderr)
> +    exit(1)
> +
>  schema.visit(QAPISchemaTestVisitor())
> 
>  for doc in schema.docs:
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
  2018-02-12 19:56   ` Eric Blake
@ 2018-02-18 23:32   ` Michael Roth
  2018-02-23 17:29     ` Markus Armbruster
  1 sibling, 1 reply; 110+ messages in thread
From: Michael Roth @ 2018-02-18 23:32 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:52)
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index dce289ae21..cc5a5941dd 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -290,8 +290,12 @@ class QAPISchemaParser(object):
>                  if not isinstance(include, str):
>                      raise QAPISemError(info,
>                                         "Value of 'include' must be a string")
> -                self._include(include, info, os.path.dirname(self.fname),
> -                              previously_included)
> +                exprs_include = self._include(include, info,
> +                                              os.path.dirname(self.fname),
> +                                              previously_included)
> +                if exprs_include:
> +                    self.exprs.extend(exprs_include.exprs)
> +                    self.docs.extend(exprs_include.docs)
>              elif "pragma" in expr:
>                  self.reject_expr_doc(cur_doc)
>                  if len(expr) != 1:
> @@ -334,14 +338,13 @@ class QAPISchemaParser(object):
> 
>          # skip multiple include of the same file
>          if incl_abs_fname in previously_included:
> -            return
> +            return None
> +
>          try:
>              fobj = open(incl_fname, 'r')
>          except IOError as e:
>              raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
> -        exprs_include = QAPISchemaParser(fobj, previously_included, info)
> -        self.exprs.extend(exprs_include.exprs)
> -        self.docs.extend(exprs_include.docs)

minor nit, but the function of _include() seems more appropriately
described now as _parse_include() or _parse_if_new() or something similar.
Maybe it would be more readable to just move the previously_included
checks into init() and just drop _include() entirely?

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> +        return QAPISchemaParser(fobj, previously_included, info)
> 
>      def _pragma(self, name, value, info):
>          global doc_required, returns_whitelist, name_case_whitelist
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
  2018-02-12 20:03   ` Eric Blake
@ 2018-02-18 23:57   ` Michael Roth
  2018-02-23 17:31     ` Markus Armbruster
  1 sibling, 1 reply; 110+ messages in thread
From: Michael Roth @ 2018-02-18 23:57 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:53)
> The parse tree is a list of expressions.  Except include expressions
> currently get replaced by the included file's parse tree.
> 
> Instead of throwing away the include expression, keep it with the file
> name expanded so you don't have to track the including file's
> directory to make sense of it.
> 
> A future commit will put this include expression to use.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  scripts/qapi/common.py | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index cc5a5941dd..6d49709784 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -290,8 +290,11 @@ class QAPISchemaParser(object):
>                  if not isinstance(include, str):
>                      raise QAPISemError(info,
>                                         "Value of 'include' must be a string")
> -                exprs_include = self._include(include, info,
> -                                              os.path.dirname(self.fname),
> +                incl_fname = os.path.join(os.path.dirname(self.fname),
> +                                          include)
> +                self.exprs.append({'expr': {'include': incl_fname},
> +                                   'info': info})
> +                exprs_include = self._include(include, info, incl_fname,
>                                                previously_included)
>                  if exprs_include:
>                      self.exprs.extend(exprs_include.exprs)
> @@ -326,8 +329,7 @@ class QAPISchemaParser(object):
>                  "Documentation for '%s' is not followed by the definition"
>                  % doc.symbol)
> 
> -    def _include(self, include, info, base_dir, previously_included):
> -        incl_fname = os.path.join(base_dir, include)
> +    def _include(self, include, info, incl_fname, previously_included):
>          incl_abs_fname = os.path.abspath(incl_fname)
>          # catch inclusion cycle
>          inf = info
> @@ -893,6 +895,9 @@ def check_exprs(exprs):
>          info = expr_elem['info']
>          doc = expr_elem.get('doc')
> 
> +        if 'include' in expr:
> +            continue
> +
>          if not doc and doc_required:
>              raise QAPISemError(info,
>                                 "Expression missing documentation comment")
> @@ -931,6 +936,9 @@ def check_exprs(exprs):
> 
>      # Try again for hidden UnionKind enum
>      for expr_elem in exprs:
> +        if 'include' in expr:
> +            continue
> +

Wouldn't this ^

>          expr = expr_elem['expr']

Need to come after this?

>          if 'union' in expr and not discriminator_find_enum_define(expr):
>              name = '%sKind' % expr['union']
> @@ -943,6 +951,9 @@ def check_exprs(exprs):
> 
>      # Validate that exprs make sense
>      for expr_elem in exprs:
> +        if 'include' in expr:
> +            continue
> +
>          expr = expr_elem['expr']

And here.

>          info = expr_elem['info']
>          doc = expr_elem.get('doc')
> @@ -1667,6 +1678,8 @@ class QAPISchema(object):
>                  self._def_command(expr, info, doc)
>              elif 'event' in expr:
>                  self._def_event(expr, info, doc)
> +            elif 'include' in expr:
> +                pass
>              else:
>                  assert False
> 
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
  2018-02-12 20:06   ` Eric Blake
@ 2018-02-19  0:01   ` Michael Roth
  1 sibling, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19  0:01 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:54)
> The generators' conversion to visitors (merge commit 9e72681d16)
> changed the processing order of entities from source order to
> alphabetical order.  The next commit needs source order, so change it
> back.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi/common.py                   |   6 +-
>  tests/qapi-schema/comments.out           |   2 +-
>  tests/qapi-schema/doc-bad-section.out    |   4 +-
>  tests/qapi-schema/doc-good.out           |  32 ++--
>  tests/qapi-schema/empty.out              |   2 +-
>  tests/qapi-schema/event-case.out         |   2 +-
>  tests/qapi-schema/ident-with-escape.out  |   6 +-
>  tests/qapi-schema/include-relpath.out    |   2 +-
>  tests/qapi-schema/include-repetition.out |   2 +-
>  tests/qapi-schema/include-simple.out     |   2 +-
>  tests/qapi-schema/indented-expr.out      |   2 +-
>  tests/qapi-schema/qapi-schema-test.out   | 320 +++++++++++++++----------------
>  12 files changed, 192 insertions(+), 190 deletions(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 6d49709784..b531ab519f 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1475,6 +1475,7 @@ class QAPISchema(object):
>          parser = QAPISchemaParser(open(fname, 'r'))
>          exprs = check_exprs(parser.exprs)
>          self.docs = parser.docs
> +        self._entity_list = []
>          self._entity_dict = {}
>          self._predefining = True
>          self._def_predefineds()
> @@ -1486,6 +1487,7 @@ class QAPISchema(object):
>          # Only the predefined types are allowed to not have info
>          assert ent.info or self._predefining
>          assert ent.name not in self._entity_dict
> +        self._entity_list.append(ent)
>          self._entity_dict[ent.name] = ent
> 
>      def lookup_entity(self, name, typ=None):
> @@ -1684,12 +1686,12 @@ class QAPISchema(object):
>                  assert False
> 
>      def check(self):
> -        for (name, ent) in sorted(self._entity_dict.items()):
> +        for ent in self._entity_list:
>              ent.check(self)
> 
>      def visit(self, visitor):
>          visitor.visit_begin(self)
> -        for (name, entity) in sorted(self._entity_dict.items()):
> +        for entity in self._entity_list:
>              if visitor.visit_needed(entity):
>                  entity.visit(visitor)
>          visitor.visit_end()
> diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
> index 17e652535c..0261ddf202 100644
> --- a/tests/qapi-schema/comments.out
> +++ b/tests/qapi-schema/comments.out
> @@ -1,4 +1,4 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
> -object q_empty
> diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out
> index 089bde1381..23bf8c71ab 100644
> --- a/tests/qapi-schema/doc-bad-section.out
> +++ b/tests/qapi-schema/doc-bad-section.out
> @@ -1,7 +1,7 @@
> -enum Enum ['one', 'two']
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
> -object q_empty
> +enum Enum ['one', 'two']
>  doc symbol=Enum
>      body=
>  == Produces *invalid* texinfo
> diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
> index 1d2c250527..0c07301f07 100644
> --- a/tests/qapi-schema/doc-good.out
> +++ b/tests/qapi-schema/doc-good.out
> @@ -1,35 +1,35 @@
> +object q_empty
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> +    prefix QTYPE
> +enum Enum ['one', 'two']
>  object Base
>      member base1: Enum optional=False
> -enum Enum ['one', 'two']
> +object Variant1
> +    member var1: str optional=False
> +object Variant2
>  object Object
>      base Base
>      tag base1
>      case one: Variant1
>      case two: Variant2
> -enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> -    prefix QTYPE
> +object q_obj_Variant1-wrapper
> +    member data: Variant1 optional=False
> +object q_obj_Variant2-wrapper
> +    member data: Variant2 optional=False
> +enum SugaredUnionKind ['one', 'two']
>  object SugaredUnion
>      member type: SugaredUnionKind optional=False
>      tag type
>      case one: q_obj_Variant1-wrapper
>      case two: q_obj_Variant2-wrapper
> -enum SugaredUnionKind ['one', 'two']
> -object Variant1
> -    member var1: str optional=False
> -object Variant2
> -command cmd q_obj_cmd-arg -> Object
> -   gen=True success_response=True boxed=False
> -command cmd-boxed Object -> None
> -   gen=True success_response=True boxed=True
> -object q_empty
> -object q_obj_Variant1-wrapper
> -    member data: Variant1 optional=False
> -object q_obj_Variant2-wrapper
> -    member data: Variant2 optional=False
>  object q_obj_cmd-arg
>      member arg1: int optional=False
>      member arg2: str optional=True
>      member arg3: bool optional=False
> +command cmd q_obj_cmd-arg -> Object
> +   gen=True success_response=True boxed=False
> +command cmd-boxed Object -> None
> +   gen=True success_response=True boxed=True
>  doc freeform
>      body=
>  = Section
> diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
> index 40b886ddae..0ec234eec4 100644
> --- a/tests/qapi-schema/empty.out
> +++ b/tests/qapi-schema/empty.out
> @@ -1,3 +1,3 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
> -object q_empty
> diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
> index 313c0fe7be..110571b793 100644
> --- a/tests/qapi-schema/event-case.out
> +++ b/tests/qapi-schema/event-case.out
> @@ -1,5 +1,5 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  event oops None
>     boxed=False
> -object q_empty
> diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
> index b5637cb2e0..8336aa7629 100644
> --- a/tests/qapi-schema/ident-with-escape.out
> +++ b/tests/qapi-schema/ident-with-escape.out
> @@ -1,7 +1,7 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
> -command fooA q_obj_fooA-arg -> None
> -   gen=True success_response=True boxed=False
> -object q_empty
>  object q_obj_fooA-arg
>      member bar1: str optional=False
> +command fooA q_obj_fooA-arg -> None
> +   gen=True success_response=True boxed=False
> diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
> index 17e652535c..0261ddf202 100644
> --- a/tests/qapi-schema/include-relpath.out
> +++ b/tests/qapi-schema/include-relpath.out
> @@ -1,4 +1,4 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
> -object q_empty
> diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
> index 17e652535c..0261ddf202 100644
> --- a/tests/qapi-schema/include-repetition.out
> +++ b/tests/qapi-schema/include-repetition.out
> @@ -1,4 +1,4 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
> -object q_empty
> diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
> index 17e652535c..0261ddf202 100644
> --- a/tests/qapi-schema/include-simple.out
> +++ b/tests/qapi-schema/include-simple.out
> @@ -1,4 +1,4 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  enum Status ['good', 'bad', 'ugly']
> -object q_empty
> diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
> index 586795f44d..34de8be426 100644
> --- a/tests/qapi-schema/indented-expr.out
> +++ b/tests/qapi-schema/indented-expr.out
> @@ -1,7 +1,7 @@
> +object q_empty
>  enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>      prefix QTYPE
>  command eins None -> None
>     gen=True success_response=True boxed=False
> -object q_empty
>  command zwei None -> None
>     gen=True success_response=True boxed=False
> diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
> index 3b1e9082d3..50706b0136 100644
> --- a/tests/qapi-schema/qapi-schema-test.out
> +++ b/tests/qapi-schema/qapi-schema-test.out
> @@ -1,87 +1,129 @@
> -alternate AltEnumBool
> -    tag type
> -    case e: EnumOne
> -    case b: bool
> -alternate AltEnumInt
> -    tag type
> -    case e: EnumOne
> -    case i: int
> -alternate AltEnumNum
> -    tag type
> -    case e: EnumOne
> -    case n: number
> -alternate AltNumEnum
> -    tag type
> -    case n: number
> -    case e: EnumOne
> -alternate AltStrObj
> -    tag type
> -    case s: str
> -    case o: TestStruct
> -event EVENT_A None
> -   boxed=False
> -event EVENT_B None
> -   boxed=False
> -event EVENT_C q_obj_EVENT_C-arg
> -   boxed=False
> -event EVENT_D q_obj_EVENT_D-arg
> -   boxed=False
> -event EVENT_E UserDefZero
> -   boxed=True
> -event EVENT_F UserDefAlternate
> -   boxed=True
> +object q_empty
> +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> +    prefix QTYPE
> +object TestStruct
> +    member integer: int optional=False
> +    member boolean: bool optional=False
> +    member string: str optional=False
> +object NestedEnumsOne
> +    member enum1: EnumOne optional=False
> +    member enum2: EnumOne optional=True
> +    member enum3: EnumOne optional=False
> +    member enum4: EnumOne optional=True
> +enum MyEnum []
>  object Empty1
>  object Empty2
>      base Empty1
> +command user_def_cmd0 Empty2 -> Empty2
> +   gen=True success_response=True boxed=False
> +enum QEnumTwo ['value1', 'value2']
> +    prefix QENUM_TWO
> +object UserDefOne
> +    base UserDefZero
> +    member string: str optional=False
> +    member enum1: EnumOne optional=True
>  enum EnumOne ['value1', 'value2', 'value3']
> -object EventStructOne
> -    member struct1: UserDefOne optional=False
> +object UserDefZero
> +    member integer: int optional=False
> +object UserDefTwoDictDict
> +    member userdef: UserDefOne optional=False
>      member string: str optional=False
> -    member enum2: EnumOne optional=True
> +object UserDefTwoDict
> +    member string1: str optional=False
> +    member dict2: UserDefTwoDictDict optional=False
> +    member dict3: UserDefTwoDictDict optional=True
> +object UserDefTwo
> +    member string0: str optional=False
> +    member dict1: UserDefTwoDict optional=False
>  object ForceArrays
>      member unused1: UserDefOneList optional=False
>      member unused2: UserDefTwoList optional=False
>      member unused3: TestStructList optional=False
> -enum MyEnum []
> -object NestedEnumsOne
> -    member enum1: EnumOne optional=False
> -    member enum2: EnumOne optional=True
> -    member enum3: EnumOne optional=False
> -    member enum4: EnumOne optional=True
> -enum QEnumTwo ['value1', 'value2']
> -    prefix QENUM_TWO
> -enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
> -    prefix QTYPE
> -object TestStruct
> -    member integer: int optional=False
> -    member boolean: bool optional=False
> -    member string: str optional=False
>  object UserDefA
>      member boolean: bool optional=False
>      member a_b: int optional=True
> -alternate UserDefAlternate
> -    tag type
> -    case udfu: UserDefFlatUnion
> -    case e: EnumOne
> -    case i: int
> -    case n: null
>  object UserDefB
>      member intb: int optional=False
>      member a-b: bool optional=True
> -object UserDefC
> -    member string1: str optional=False
> -    member string2: str optional=False
>  object UserDefFlatUnion
>      base UserDefUnionBase
>      tag enum1
>      case value1: UserDefA
>      case value2: UserDefB
>      case value3: UserDefB
> +object UserDefUnionBase
> +    base UserDefZero
> +    member string: str optional=False
> +    member enum1: EnumOne optional=False
> +object q_obj_UserDefFlatUnion2-base
> +    member integer: int optional=True
> +    member string: str optional=False
> +    member enum1: QEnumTwo optional=False
>  object UserDefFlatUnion2
>      base q_obj_UserDefFlatUnion2-base
>      tag enum1
>      case value1: UserDefC
>      case value2: UserDefB
> +object WrapAlternate
> +    member alt: UserDefAlternate optional=False
> +alternate UserDefAlternate
> +    tag type
> +    case udfu: UserDefFlatUnion
> +    case e: EnumOne
> +    case i: int
> +    case n: null
> +object UserDefC
> +    member string1: str optional=False
> +    member string2: str optional=False
> +alternate AltEnumBool
> +    tag type
> +    case e: EnumOne
> +    case b: bool
> +alternate AltEnumNum
> +    tag type
> +    case e: EnumOne
> +    case n: number
> +alternate AltNumEnum
> +    tag type
> +    case n: number
> +    case e: EnumOne
> +alternate AltEnumInt
> +    tag type
> +    case e: EnumOne
> +    case i: int
> +alternate AltStrObj
> +    tag type
> +    case s: str
> +    case o: TestStruct
> +object q_obj_intList-wrapper
> +    member data: intList optional=False
> +object q_obj_int8List-wrapper
> +    member data: int8List optional=False
> +object q_obj_int16List-wrapper
> +    member data: int16List optional=False
> +object q_obj_int32List-wrapper
> +    member data: int32List optional=False
> +object q_obj_int64List-wrapper
> +    member data: int64List optional=False
> +object q_obj_uint8List-wrapper
> +    member data: uint8List optional=False
> +object q_obj_uint16List-wrapper
> +    member data: uint16List optional=False
> +object q_obj_uint32List-wrapper
> +    member data: uint32List optional=False
> +object q_obj_uint64List-wrapper
> +    member data: uint64List optional=False
> +object q_obj_numberList-wrapper
> +    member data: numberList optional=False
> +object q_obj_boolList-wrapper
> +    member data: boolList optional=False
> +object q_obj_strList-wrapper
> +    member data: strList optional=False
> +object q_obj_sizeList-wrapper
> +    member data: sizeList optional=False
> +object q_obj_anyList-wrapper
> +    member data: anyList optional=False
> +enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
>  object UserDefNativeListUnion
>      member type: UserDefNativeListUnionKind optional=False
>      tag type
> @@ -99,133 +141,91 @@ object UserDefNativeListUnion
>      case string: q_obj_strList-wrapper
>      case sizes: q_obj_sizeList-wrapper
>      case any: q_obj_anyList-wrapper
> -enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
> -object UserDefOne
> -    base UserDefZero
> -    member string: str optional=False
> -    member enum1: EnumOne optional=True
> +command user_def_cmd None -> None
> +   gen=True success_response=True boxed=False
> +object q_obj_user_def_cmd1-arg
> +    member ud1a: UserDefOne optional=False
> +command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
> +   gen=True success_response=True boxed=False
> +object q_obj_user_def_cmd2-arg
> +    member ud1a: UserDefOne optional=False
> +    member ud1b: UserDefOne optional=True
> +command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
> +   gen=True success_response=True boxed=False
> +object q_obj_guest-get-time-arg
> +    member a: int optional=False
> +    member b: int optional=True
> +command guest-get-time q_obj_guest-get-time-arg -> int
> +   gen=True success_response=True boxed=False
> +object q_obj_guest-sync-arg
> +    member arg: any optional=False
> +command guest-sync q_obj_guest-sync-arg -> any
> +   gen=True success_response=True boxed=False
> +command boxed-struct UserDefZero -> None
> +   gen=True success_response=True boxed=True
> +command boxed-union UserDefNativeListUnion -> None
> +   gen=True success_response=True boxed=True
>  object UserDefOptions
>      member i64: intList optional=True
>      member u64: uint64List optional=True
>      member u16: uint16List optional=True
>      member i64x: int optional=True
>      member u64x: uint64 optional=True
> -object UserDefTwo
> -    member string0: str optional=False
> -    member dict1: UserDefTwoDict optional=False
> -object UserDefTwoDict
> -    member string1: str optional=False
> -    member dict2: UserDefTwoDictDict optional=False
> -    member dict3: UserDefTwoDictDict optional=True
> -object UserDefTwoDictDict
> -    member userdef: UserDefOne optional=False
> +object EventStructOne
> +    member struct1: UserDefOne optional=False
>      member string: str optional=False
> -object UserDefUnionBase
> -    base UserDefZero
> -    member string: str optional=False
> -    member enum1: EnumOne optional=False
> -object UserDefZero
> -    member integer: int optional=False
> -object WrapAlternate
> -    member alt: UserDefAlternate optional=False
> -event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
> +    member enum2: EnumOne optional=True
> +event EVENT_A None
> +   boxed=False
> +event EVENT_B None
> +   boxed=False
> +object q_obj_EVENT_C-arg
> +    member a: int optional=True
> +    member b: UserDefOne optional=True
> +    member c: str optional=False
> +event EVENT_C q_obj_EVENT_C-arg
> +   boxed=False
> +object q_obj_EVENT_D-arg
> +    member a: EventStructOne optional=False
> +    member b: str optional=False
> +    member c: str optional=True
> +    member enum3: EnumOne optional=True
> +event EVENT_D q_obj_EVENT_D-arg
>     boxed=False
> -alternate __org.qemu_x-Alt
> -    tag type
> -    case __org.qemu_x-branch: str
> -    case b: __org.qemu_x-Base
> +event EVENT_E UserDefZero
> +   boxed=True
> +event EVENT_F UserDefAlternate
> +   boxed=True
> +enum __org.qemu_x-Enum ['__org.qemu_x-value']
>  object __org.qemu_x-Base
>      member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
> -enum __org.qemu_x-Enum ['__org.qemu_x-value']
>  object __org.qemu_x-Struct
>      base __org.qemu_x-Base
>      member __org.qemu_x-member2: str optional=False
>      member wchar-t: int optional=True
> -object __org.qemu_x-Struct2
> -    member array: __org.qemu_x-Union1List optional=False
> +object q_obj_str-wrapper
> +    member data: str optional=False
> +enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
>  object __org.qemu_x-Union1
>      member type: __org.qemu_x-Union1Kind optional=False
>      tag type
>      case __org.qemu_x-branch: q_obj_str-wrapper
> -enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
> +object __org.qemu_x-Struct2
> +    member array: __org.qemu_x-Union1List optional=False
>  object __org.qemu_x-Union2
>      base __org.qemu_x-Base
>      tag __org.qemu_x-member1
>      case __org.qemu_x-value: __org.qemu_x-Struct2
> -command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
> -   gen=True success_response=True boxed=False
> -command boxed-struct UserDefZero -> None
> -   gen=True success_response=True boxed=True
> -command boxed-union UserDefNativeListUnion -> None
> -   gen=True success_response=True boxed=True
> -command guest-get-time q_obj_guest-get-time-arg -> int
> -   gen=True success_response=True boxed=False
> -command guest-sync q_obj_guest-sync-arg -> any
> -   gen=True success_response=True boxed=False
> -object q_empty
> -object q_obj_EVENT_C-arg
> -    member a: int optional=True
> -    member b: UserDefOne optional=True
> -    member c: str optional=False
> -object q_obj_EVENT_D-arg
> -    member a: EventStructOne optional=False
> -    member b: str optional=False
> -    member c: str optional=True
> -    member enum3: EnumOne optional=True
> -object q_obj_UserDefFlatUnion2-base
> -    member integer: int optional=True
> -    member string: str optional=False
> -    member enum1: QEnumTwo optional=False
> +alternate __org.qemu_x-Alt
> +    tag type
> +    case __org.qemu_x-branch: str
> +    case b: __org.qemu_x-Base
> +event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
> +   boxed=False
>  object q_obj___org.qemu_x-command-arg
>      member a: __org.qemu_x-EnumList optional=False
>      member b: __org.qemu_x-StructList optional=False
>      member c: __org.qemu_x-Union2 optional=False
>      member d: __org.qemu_x-Alt optional=False
> -object q_obj_anyList-wrapper
> -    member data: anyList optional=False
> -object q_obj_boolList-wrapper
> -    member data: boolList optional=False
> -object q_obj_guest-get-time-arg
> -    member a: int optional=False
> -    member b: int optional=True
> -object q_obj_guest-sync-arg
> -    member arg: any optional=False
> -object q_obj_int16List-wrapper
> -    member data: int16List optional=False
> -object q_obj_int32List-wrapper
> -    member data: int32List optional=False
> -object q_obj_int64List-wrapper
> -    member data: int64List optional=False
> -object q_obj_int8List-wrapper
> -    member data: int8List optional=False
> -object q_obj_intList-wrapper
> -    member data: intList optional=False
> -object q_obj_numberList-wrapper
> -    member data: numberList optional=False
> -object q_obj_sizeList-wrapper
> -    member data: sizeList optional=False
> -object q_obj_str-wrapper
> -    member data: str optional=False
> -object q_obj_strList-wrapper
> -    member data: strList optional=False
> -object q_obj_uint16List-wrapper
> -    member data: uint16List optional=False
> -object q_obj_uint32List-wrapper
> -    member data: uint32List optional=False
> -object q_obj_uint64List-wrapper
> -    member data: uint64List optional=False
> -object q_obj_uint8List-wrapper
> -    member data: uint8List optional=False
> -object q_obj_user_def_cmd1-arg
> -    member ud1a: UserDefOne optional=False
> -object q_obj_user_def_cmd2-arg
> -    member ud1a: UserDefOne optional=False
> -    member ud1b: UserDefOne optional=True
> -command user_def_cmd None -> None
> -   gen=True success_response=True boxed=False
> -command user_def_cmd0 Empty2 -> Empty2
> -   gen=True success_response=True boxed=False
> -command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
> -   gen=True success_response=True boxed=False
> -command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
> +command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
>     gen=True success_response=True boxed=False
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
  2018-02-12 20:56   ` Eric Blake
  2018-02-13 15:25   ` Marc-Andre Lureau
@ 2018-02-19  0:21   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19  0:21 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:56)
> All generated .c are named like their .h, except for qmp-marshal.c and
> qmp-commands.h.  To add to the confusion, tests-qmp-commands.c falsely
> matches generated test-qmp-commands.h.
> 
> Get rid of this unnecessary complication.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore                                     |  3 +--
>  Makefile                                       |  6 +++---
>  Makefile.objs                                  |  2 +-
>  docs/devel/qapi-code-gen.txt                   |  6 +++---
>  qga/Makefile.objs                              |  2 +-
>  scripts/qapi/commands.py                       |  2 +-
>  tests/.gitignore                               |  5 ++---
>  tests/Makefile.include                         | 10 +++++-----
>  tests/{test-qmp-commands.c => test-qmp-cmds.c} |  0
>  9 files changed, 17 insertions(+), 19 deletions(-)
>  rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (100%)
> 
> diff --git a/.gitignore b/.gitignore
> index 2f9a92f6cc..7d783e6e66 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -33,9 +33,8 @@
>  /qapi-visit.[ch]
>  /qapi-event.[ch]
>  /qapi-doc.texi
> -/qmp-commands.h
> +/qmp-commands.[ch]
>  /qmp-introspect.[ch]
> -/qmp-marshal.c
>  /qemu-doc.html
>  /qemu-doc.info
>  /qemu-doc.txt
> diff --git a/Makefile b/Makefile
> index bd781c6aad..164a38578e 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -91,7 +91,7 @@ include $(SRC_PATH)/rules.mak
> 
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
>  GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> -GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
> +GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
>  GENERATED_FILES += qmp-introspect.h
>  GENERATED_FILES += qmp-introspect.c
>  GENERATED_FILES += qapi-doc.texi
> @@ -496,7 +496,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
> 
>  qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
>  qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
> -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \
> +qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
>  qga/qapi-generated/qga-qapi-doc.texi: \
>  qga/qapi-generated/qapi-gen-timestamp ;
>  qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
> @@ -522,7 +522,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
> 
>  qapi-types.c qapi-types.h \
>  qapi-visit.c qapi-visit.h \
> -qmp-commands.h qmp-marshal.c \
> +qmp-commands.h qmp-commands.c \
>  qapi-event.c qapi-event.h \
>  qmp-introspect.h qmp-introspect.c \
>  qapi-doc.texi: \
> diff --git a/Makefile.objs b/Makefile.objs
> index 2efba6d768..d255aaf194 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -78,7 +78,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
>  ######################################################################
>  # qapi
> 
> -common-obj-y += qmp-marshal.o
> +common-obj-y += qmp-commands.o
>  common-obj-y += qmp-introspect.o
>  common-obj-y += qmp.o hmp.o
>  endif
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index 1a1cbaea7b..ba1dc73298 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -1147,8 +1147,8 @@ declares qmp_COMMAND() that the user must implement.
> 
>  The following files are generated:
> 
> -$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each
> -                        QMP command defined in the schema
> +$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
> +                         QMP command defined in the schema
> 
>  $(prefix)qmp-commands.h: Function prototypes for the QMP commands
>                           specified in the schema
> @@ -1170,7 +1170,7 @@ Example:
>      void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
> 
>      #endif
> -    $ cat qapi-generated/example-qmp-marshal.c
> +    $ cat qapi-generated/example-qmp-commands.c
>  [Uninteresting stuff omitted...]
> 
>      static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
> diff --git a/qga/Makefile.objs b/qga/Makefile.objs
> index 1c5986c0bb..6151378ae4 100644
> --- a/qga/Makefile.objs
> +++ b/qga/Makefile.objs
> @@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
>  qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
>  qga-obj-$(CONFIG_WIN32) += vss-win32.o
>  qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
> -qga-obj-y += qapi-generated/qga-qmp-marshal.o
> +qga-obj-y += qapi-generated/qga-qmp-commands.o
> 
>  qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index a744611d58..05fe33a03b 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -289,5 +289,5 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>      schema.visit(vis)
>      genc.add(vis.defn)
>      genh.add(vis.decl)
> -    genc.write(output_dir, prefix + 'qmp-marshal.c')
> +    genc.write(output_dir, prefix + 'qmp-commands.c')
>      genh.write(output_dir, prefix + 'qmp-commands.h')
> diff --git a/tests/.gitignore b/tests/.gitignore
> index e5c744b7ed..2629cfc2f9 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -70,13 +70,12 @@ test-qdist
>  test-qga
>  test-qht
>  test-qht-par
> -test-qmp-commands
> -test-qmp-commands.h
> +test-qmp-cmds
> +test-qmp-commands.[ch]
>  test-qmp-event
>  test-qobject-input-strict
>  test-qobject-input-visitor
>  test-qmp-introspect.[ch]
> -test-qmp-marshal.c
>  test-qobject-output-visitor
>  test-rcu-list
>  test-replication
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index b406531b34..9a21ed7ee9 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -61,8 +61,8 @@ check-unit-y += tests/test-clone-visitor$(EXESUF)
>  gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
>  check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
>  gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
> -check-unit-y += tests/test-qmp-commands$(EXESUF)
> -gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
> +check-unit-y += tests/test-qmp-cmds$(EXESUF)
> +gcov-files-test-qmp-cmds-y = qapi/qmp-dispatch.c
>  check-unit-y += tests/test-string-input-visitor$(EXESUF)
>  gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
>  check-unit-y += tests/test-string-output-visitor$(EXESUF)
> @@ -576,7 +576,7 @@ test-obj-y = tests/check-qnum.o tests/check-qstring.o tests/check-qdict.o \
>         tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
>         tests/test-clone-visitor.o \
>         tests/test-qobject-input-visitor.o \
> -       tests/test-qmp-commands.o tests/test-visitor-serialization.o \
> +       tests/test-qmp-cmds.o tests/test-visitor-serialization.o \
>         tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
>         tests/test-opts-visitor.o tests/test-qmp-event.o \
>         tests/rcutorture.o tests/test-rcu-list.o \
> @@ -656,7 +656,7 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
> 
>  tests/test-qapi-types.c tests/test-qapi-types.h \
>  tests/test-qapi-visit.c tests/test-qapi-visit.h \
> -tests/test-qmp-commands.h tests/test-qmp-marshal.c \
> +tests/test-qmp-commands.h tests/test-qmp-commands.c \
>  tests/test-qapi-event.c tests/test-qapi-event.h \
>  tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
>  tests/test-qapi-gen-timestamp ;
> @@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
>  tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
>  tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
>  tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
> -tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
> +tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
>  tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
>  tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
> 
> diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-cmds.c
> similarity index 100%
> rename from tests/test-qmp-commands.c
> rename to tests/test-qmp-cmds.c
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
  2018-02-12 21:06   ` Eric Blake
  2018-02-13 15:25   ` Marc-Andre Lureau
@ 2018-02-19 15:52   ` Michael Roth
  2018-02-23 17:35     ` Markus Armbruster
  2 siblings, 1 reply; 110+ messages in thread
From: Michael Roth @ 2018-02-19 15:52 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:57)
> The use of QAPIGen is rather shallow so far: most of the output
> accumulation is not converted.  Take the next step: convert output
> accumulation in the code-generating visitor classes.  Helper functions
> outside these classes are not converted.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  scripts/qapi/commands.py   | 71 ++++++++++++++++------------------------
>  scripts/qapi/common.py     | 13 ++++++++
>  scripts/qapi/doc.py        | 74 ++++++++++++++++++++----------------------
>  scripts/qapi/events.py     | 55 ++++++++++++-------------------
>  scripts/qapi/introspect.py | 56 +++++++++++++-------------------
>  scripts/qapi/types.py      | 81 +++++++++++++++++++---------------------------
>  scripts/qapi/visit.py      | 80 +++++++++++++++++++--------------------------
>  7 files changed, 188 insertions(+), 242 deletions(-)
> 

<snip>

> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 29d98ca934..31d2f73e7e 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -2049,3 +2049,16 @@ class QAPIGenDoc(QAPIGen):
>      def _top(self, fname):
>          return (QAPIGen._top(self, fname)
>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
> +
> +
> +class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
> +
> +    def __init__(self, prefix, what, blurb, pydoc):
> +        self._prefix = prefix
> +        self._what = what
> +        self._genc = QAPIGenC(blurb, pydoc)
> +        self._genh = QAPIGenH(blurb, pydoc)
> +
> +    def write(self, output_dir):
> +        self._genc.write(output_dir, self._prefix + self._what + '.c')
> +        self._genh.write(output_dir, self._prefix + self._what + '.h')

minor nit: since subclasses of QAPISchemaVisitor and
QAPISchemaMonolithicCVisitor all rely on .write() now, should we declare it
in the abstract QAPISchemaVisitor?

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

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

* Re: [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames Markus Armbruster
@ 2018-02-19 18:18   ` Michael Roth
  0 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 18:18 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:59)
> guardname() fails to return a valid C identifier for arguments
> containing anything but [A-Za-z0-9_.-'].  Fix that.  Don't bother
> protecting ticklish identifiers; header guards are all-caps, and no
> ticklish identifiers are.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  scripts/qapi/common.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index de12f8469a..6e5152b173 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1867,7 +1867,7 @@ def mcgen(code, **kwds):
> 
> 
>  def guardname(filename):
> -    return c_name(filename, protect=False).upper()
> +    return re.sub(r'[^A-Za-z0-9_]', '_', filename).upper()
> 
> 
>  def guardstart(name):
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
  2018-02-12 21:44   ` Eric Blake
  2018-02-13 15:25   ` Marc-Andre Lureau
@ 2018-02-19 19:30   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:30 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:35:58)
> Linking code from multiple separate QAPI schemata into the same
> program is possible, but involves some weirdness around built-in
> types:
> 
> * We generate code for built-in types into .c only with option
>   --builtins.  The user is responsible for generating code for exactly
>   one QAPI schema per program with --builtins.
> 
> * We generate code for built-in types into .h regardless of
>   --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN.  Because all
>   copies of this code are exactly the same, including any combination
>   of these headers works.
> 
> Replace this contraption by something more conventional: generate code
> for built-in types into their very own files: qapi-builtin-types.c,
> qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
> only with --builtins.  Obey --output-dir, but ignore --prefix for
> them.
> 
> Make qapi-types.h include qapi-builtin-types.h.  With multiple
> schemata you now have multiple qapi-types.[ch], but only one
> qapi-builtin-types.[ch].  Same for qapi-visit.[ch] and
> qapi-builtin-visit.[ch].
> 
> Bonus: if all you need is built-in stuff, you can include a much
> smaller header.  To be exploited shortly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore             |  2 ++
>  Makefile               | 13 ++++++----
>  Makefile.objs          |  2 ++
>  scripts/qapi/common.py | 61 ++++++++++++++++++++++++++++++++++++++++-------
>  scripts/qapi/types.py  | 61 +++++++++++++++++++----------------------------
>  scripts/qapi/visit.py  | 64 +++++++++++++++++++++-----------------------------
>  6 files changed, 116 insertions(+), 87 deletions(-)
> 
> diff --git a/.gitignore b/.gitignore
> index 7d783e6e66..9477a08b6b 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -29,6 +29,8 @@
>  /qga/qapi-generated
>  /qapi-generated
>  /qapi-gen-timestamp
> +/qapi-builtin-types.[ch]
> +/qapi-builtin-visit.[ch]
>  /qapi-types.[ch]
>  /qapi-visit.[ch]
>  /qapi-event.[ch]
> diff --git a/Makefile b/Makefile
> index 164a38578e..60ddc9c945 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -90,10 +90,13 @@ endif
>  include $(SRC_PATH)/rules.mak
> 
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
> -GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> -GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c
> -GENERATED_FILES += qmp-introspect.h
> -GENERATED_FILES += qmp-introspect.c
> +GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
> +GENERATED_FILES += qapi-types.h qapi-types.c
> +GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
> +GENERATED_FILES += qapi-visit.h qapi-visit.c
> +GENERATED_FILES += qmp-commands.h qmp-commands.c
> +GENERATED_FILES += qapi-event.h qapi-event.c
> +GENERATED_FILES += qmp-introspect.c qmp-introspect.h
>  GENERATED_FILES += qapi-doc.texi
> 
>  GENERATED_FILES += trace/generated-tcg-tracers.h
> @@ -520,7 +523,9 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/transaction.json \
>                 $(SRC_PATH)/qapi/ui.json
> 
> +qapi-builtin-types.c qapi-builtin-types.h \
>  qapi-types.c qapi-types.h \
> +qapi-builtin-visit.c qapi-builtin-visit.h \
>  qapi-visit.c qapi-visit.h \
>  qmp-commands.h qmp-commands.c \
>  qapi-event.c qapi-event.h \
> diff --git a/Makefile.objs b/Makefile.objs
> index d255aaf194..2813e984fd 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -2,6 +2,8 @@
>  # Common libraries for tools and emulators
>  stub-obj-y = stubs/ crypto/
>  util-obj-y = util/ qobject/ qapi/
> +util-obj-y += qapi-builtin-types.o
> +util-obj-y += qapi-builtin-visit.o
>  util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
> 
>  chardev-obj-y = chardev/
> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
> index 31d2f73e7e..de12f8469a 100644
> --- a/scripts/qapi/common.py
> +++ b/scripts/qapi/common.py
> @@ -1531,11 +1531,10 @@ class QAPISchema(object):
> 
>      def _def_builtin_type(self, name, json_type, c_type):
>          self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
> -        # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
> -        # qapi-types.h from a single .c, all arrays of builtins must be
> -        # declared in the first file whether or not they are used.  Nicer
> -        # would be to use lazy instantiation, while figuring out how to
> -        # avoid compilation issues with multiple qapi-types.h.
> +        # Instantiating only the arrays that are actually used would
> +        # be nice, but we can't as long as their generated code
> +        # (qapi-builtin-types.[ch]) may be shared by some other
> +        # schema.
>          self._make_array_type(name, None)
> 
>      def _def_predefineds(self):
> @@ -1992,14 +1991,15 @@ class QAPIGen(object):
>          return ''
> 
>      def write(self, output_dir, fname):
> -        if output_dir:
> +        pathname = os.path.join(output_dir, fname)
> +        dir = os.path.dirname(pathname)
> +        if dir:
>              try:
> -                os.makedirs(output_dir)
> +                os.makedirs(dir)
>              except os.error as e:
>                  if e.errno != errno.EEXIST:
>                      raise
> -        fd = os.open(os.path.join(output_dir, fname),
> -                     os.O_RDWR | os.O_CREAT, 0666)
> +        fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0666)
>          f = os.fdopen(fd, 'r+')
>          text = (self._top(fname) + self._preamble + self._body
>                  + self._bottom(fname))
> @@ -2046,6 +2046,7 @@ class QAPIGenH(QAPIGenC):
> 
> 
>  class QAPIGenDoc(QAPIGen):
> +
>      def _top(self, fname):
>          return (QAPIGen._top(self, fname)
>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
> @@ -2062,3 +2063,45 @@ class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
>      def write(self, output_dir):
>          self._genc.write(output_dir, self._prefix + self._what + '.c')
>          self._genh.write(output_dir, self._prefix + self._what + '.h')
> +
> +
> +class QAPISchemaModularCVisitor(QAPISchemaVisitor):
> +
> +    def __init__(self, prefix, what, blurb, pydoc):
> +        self._prefix = prefix
> +        self._what = what
> +        self._blurb = blurb
> +        self._pydoc = pydoc
> +        self._module = {}
> +
> +    def _module_basename(self, what, name):
> +        if name is None:
> +            return re.sub(r'-', '-builtin-', what)
> +        return self._prefix + what
> +
> +    def _add_module(self, name, blurb):
> +        genc = QAPIGenC(blurb, self._pydoc)
> +        genh = QAPIGenH(blurb, self._pydoc)
> +        self._module[name] = (genc, genh)
> +        self._set_module(name)
> +
> +    def _set_module(self, name):
> +        self._genc, self._genh = self._module[name]
> +
> +    def write(self, output_dir, opt_builtins):
> +        for name in self._module:
> +            if name is None and not opt_builtins:
> +                continue
> +            basename = self._module_basename(self._what, name)
> +            (genc, genh) = self._module[name]
> +            genc.write(output_dir, basename + '.c')
> +            genh.write(output_dir, basename + '.h')
> +
> +    def _begin_module(self, name):
> +        pass
> +
> +    def visit_module(self, name):
> +        if len(self._module) != 1:
> +            return
> +        self._add_module(name, self._blurb)
> +        self._begin_module(name)
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index d2b8423479..59826b1162 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -167,64 +167,51 @@ void qapi_free_%(c_name)s(%(c_name)s *obj)
>      return ret
> 
> 
> -class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
> +class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
> 
> -    def __init__(self, prefix, opt_builtins):
> -        QAPISchemaMonolithicCVisitor.__init__(
> +    def __init__(self, prefix):
> +        QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
>              __doc__)
> -        self._opt_builtins = opt_builtins
> +        self._add_module(None, ' * Built-in QAPI types')
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qapi/dealloc-visitor.h"
> +#include "qapi-builtin-types.h"
> +#include "qapi-builtin-visit.h"
> +'''))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/util.h"
> +'''))
> +
> +    def _begin_module(self, name):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
>  #include "%(prefix)sqapi-types.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -                                      prefix=prefix))
> +                                      prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi/util.h"
> +#include "qapi-builtin-types.h"
>  '''))
> -        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
> 
>      def visit_begin(self, schema):
>          # gen_object() is recursive, ensure it doesn't visit the empty type
>          objects_seen.add(schema.the_empty_object_type.name)
> 
> -    def visit_end(self):
> -        # To avoid header dependency hell, we always generate
> -        # declarations for built-in types in our header files and
> -        # simply guard them.  See also opt_builtins (command line
> -        # option -b).
> -        self._btin += guardend('QAPI_TYPES_BUILTIN')
> -        self._genh.preamble_add(self._btin)
> -        self._btin = None
> -
>      def _gen_type_cleanup(self, name):
>          self._genh.add(gen_type_cleanup_decl(name))
>          self._genc.add(gen_type_cleanup(name))
> 
>      def visit_enum_type(self, name, info, values, prefix):
> -        # Special case for our lone builtin enum type
> -        # TODO use something cleaner than existence of info
> -        if not info:
> -            self._btin += gen_enum(name, values, prefix)
> -            if self._opt_builtins:
> -                self._genc.add(gen_enum_lookup(name, values, prefix))
> -        else:
> -            self._genh.preamble_add(gen_enum(name, values, prefix))
> -            self._genc.add(gen_enum_lookup(name, values, prefix))
> +        self._genh.preamble_add(gen_enum(name, values, prefix))
> +        self._genc.add(gen_enum_lookup(name, values, prefix))
> 
>      def visit_array_type(self, name, info, element_type):
> -        if isinstance(element_type, QAPISchemaBuiltinType):
> -            self._btin += gen_fwd_object_or_array(name)
> -            self._btin += gen_array(name, element_type)
> -            self._btin += gen_type_cleanup_decl(name)
> -            if self._opt_builtins:
> -                self._genc.add(gen_type_cleanup(name))
> -        else:
> -            self._genh.preamble_add(gen_fwd_object_or_array(name))
> -            self._genh.add(gen_array(name, element_type))
> -            self._gen_type_cleanup(name)
> +        self._genh.preamble_add(gen_fwd_object_or_array(name))
> +        self._genh.add(gen_array(name, element_type))
> +        self._gen_type_cleanup(name)
> 
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
> @@ -248,6 +235,6 @@ class QAPISchemaGenTypeVisitor(QAPISchemaMonolithicCVisitor):
> 
> 
>  def gen_types(schema, output_dir, prefix, opt_builtins):
> -    vis = QAPISchemaGenTypeVisitor(prefix, opt_builtins)
> +    vis = QAPISchemaGenTypeVisitor(prefix)
>      schema.visit(vis)
> -    vis.write(output_dir)
> +    vis.write(output_dir, opt_builtins)
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index 3d09d44265..9b678e7263 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -263,13 +263,27 @@ out:
>                   c_name=c_name(name))
> 
> 
> -class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
> +class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
> 
> -    def __init__(self, prefix, opt_builtins):
> -        QAPISchemaMonolithicCVisitor.__init__(
> +    def __init__(self, prefix):
> +        QAPISchemaModularCVisitor.__init__(
>              self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
>              __doc__)
> -        self._opt_builtins = opt_builtins
> +        self._add_module(None, ' * Built-in QAPI visitors')
> +        self._genc.preamble_add(mcgen('''
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qapi/error.h"
> +#include "qapi-builtin-visit.h"
> +'''))
> +        self._genh.preamble_add(mcgen('''
> +#include "qapi/visitor.h"
> +#include "qapi-builtin-types.h"
> +
> +''',
> +                                      prefix=prefix))
> +
> +    def _begin_module(self, name):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> @@ -277,45 +291,21 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
>  #include "qapi/qmp/qerror.h"
>  #include "%(prefix)sqapi-visit.h"
>  ''',
> -                                      prefix=prefix))
> +                                      prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi/visitor.h"
> +#include "qapi-builtin-visit.h"
>  #include "%(prefix)sqapi-types.h"
> 
>  ''',
> -                                      prefix=prefix))
> -        self._btin = guardstart('QAPI_VISIT_BUILTIN')
> -
> -    def visit_end(self):
> -        # To avoid header dependency hell, we always generate
> -        # declarations for built-in types in our header files and
> -        # simply guard them.  See also opt_builtins (command line
> -        # option -b).
> -        self._btin += guardend('QAPI_VISIT_BUILTIN')
> -        self._genh.preamble_add(self._btin)
> -        self._btin = None
> +                                      prefix=self._prefix))
> 
>      def visit_enum_type(self, name, info, values, prefix):
> -        # Special case for our lone builtin enum type
> -        # TODO use something cleaner than existence of info
> -        if not info:
> -            self._btin += gen_visit_decl(name, scalar=True)
> -            if self._opt_builtins:
> -                self._genc.add(gen_visit_enum(name))
> -        else:
> -            self._genh.add(gen_visit_decl(name, scalar=True))
> -            self._genc.add(gen_visit_enum(name))
> +        self._genh.add(gen_visit_decl(name, scalar=True))
> +        self._genc.add(gen_visit_enum(name))
> 
>      def visit_array_type(self, name, info, element_type):
> -        decl = gen_visit_decl(name)
> -        defn = gen_visit_list(name, element_type)
> -        if isinstance(element_type, QAPISchemaBuiltinType):
> -            self._btin += decl
> -            if self._opt_builtins:
> -                self._genc.add(defn)
> -        else:
> -            self._genh.add(decl)
> -            self._genc.add(defn)
> +        self._genh.add(gen_visit_decl(name))
> +        self._genc.add(gen_visit_list(name, element_type))
> 
>      def visit_object_type(self, name, info, base, members, variants):
>          # Nothing to do for the special empty builtin
> @@ -336,6 +326,6 @@ class QAPISchemaGenVisitVisitor(QAPISchemaMonolithicCVisitor):
> 
> 
>  def gen_visit(schema, output_dir, prefix, opt_builtins):
> -    vis = QAPISchemaGenVisitVisitor(prefix, opt_builtins)
> +    vis = QAPISchemaGenVisitVisitor(prefix)
>      schema.visit(vis)
> -    vis.write(output_dir)
> +    vis.write(output_dir, opt_builtins)
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
  2018-02-12 22:27   ` Eric Blake
  2018-02-13 16:00   ` Marc-Andre Lureau
@ 2018-02-19 19:33   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:33 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:36:03)
> With modular code generation, putting stuff right into
> qapi-schema.json is a bad idea.  Update writing-qmp-commands.txt
> accordingly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  docs/devel/writing-qmp-commands.txt | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 4f5b24c0c4..776b3b41ca 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -15,8 +15,8 @@ start with docs/interop/qmp-intro.txt.
>  Generally speaking, the following steps should be taken in order to write a
>  new QMP command.
> 
> -1. Write the command's and type(s) specification in the QAPI schema file
> -   (qapi-schema.json in the root source directory)
> +1. Define the command and any types it needs in the appropriate QAPI
> +   schema module.
> 
>  2. Write the QMP command itself, which is a regular C function. Preferably,
>     the command should be exported by some QEMU subsystem. But it can also be
> @@ -88,8 +88,9 @@ command carries some meaningful action in QEMU but here it will just print
>  Our command will be called "hello-world". It takes no arguments, nor does it
>  return any data.
> 
> -The first step is to add the following line to the bottom of the
> -qapi-schema.json file:
> +The first step is defining the command in the appropriate QAPI schema
> +module.  We pick module qapi/misc.json, and add the following line at
> +the bottom:
> 
>  { 'command': 'hello-world' }
> 
> @@ -245,7 +246,7 @@ This is very important. No QMP command will be accepted in QEMU without proper
>  documentation.
> 
>  There are many examples of such documentation in the schema file already, but
> -here goes "hello-world"'s new entry for the qapi-schema.json file:
> +here goes "hello-world"'s new entry for qapi/misc.json:
> 
>  ##
>  # @hello-world
> @@ -425,8 +426,7 @@ There are a number of things to be noticed:
>     allocated by the implementation. This is so because the QAPI also generates
>     a function to free its types and it cannot distinguish between dynamically
>     or statically allocated strings
> -6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
> -   otherwise qemu won't build
> +6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
> 
>  Time to test the new command. Build qemu, run it as described in the "Testing"
>  section and try this:
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
  2018-02-12 22:29   ` Eric Blake
  2018-02-13 16:03   ` Marc-Andre Lureau
@ 2018-02-19 19:35   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:35 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:36:04)
> * Fix guidance on error classes
> 
> * Point to generated documentation
> 
> * Drop plea for documentation, because the QAPI code generator
>   enforces it since commit 3313b6124b
> 
> * Minor tweaks here and there
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  docs/devel/writing-qmp-commands.txt | 25 +++++++++----------------
>  docs/interop/qmp-intro.txt          |  3 ++-
>  2 files changed, 11 insertions(+), 17 deletions(-)
> 
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 776b3b41ca..50385eff27 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -36,9 +36,9 @@ very simple and get more complex as we progress.
>  For all the examples in the next sections, the test setup is the same and is
>  shown here.
> 
> -First, QEMU should be started as:
> +First, QEMU should be started like this:
> 
> -# /path/to/your/source/qemu [...] \
> +# qemu-system-TARGET [...] \
>      -chardev socket,id=qmp,port=4444,host=localhost,server \
>      -mon chardev=qmp,mode=control,pretty=on
> 
> @@ -179,7 +179,7 @@ described in the "Testing" section and then send two commands:
>      }
>  }
> 
> -You should see "Hello, world" and "we love qemu" in the terminal running qemu,
> +You should see "Hello, world" and "We love qemu" in the terminal running qemu,
>  if you don't see these strings, then something went wrong.
> 
>  === Errors ===
> @@ -221,30 +221,23 @@ The QMP server's response should be:
>      }
>  }
> 
> -As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR
> -(done by default when using error_setg()). There are two exceptions to
> -this rule:
> +Note that error_setg() produces a "GenericError" class.  In general,
> +all QMP errors should have that error class.  There are two exceptions
> +to this rule:
> 
> - 1. A non-generic ErrorClass value exists* for the failure you want to report
> -    (eg. DeviceNotFound)
> + 1. To support a management application's need to recognize a specific
> +    error for special handling
> 
> - 2. Management applications have to take special action on the failure you
> -    want to report, hence you have to add a new ErrorClass value so that they
> -    can check for it
> + 2. Backward compatibility
> 
>  If the failure you want to report falls into one of the two cases above,
>  use error_set() with a second argument of an ErrorClass value.
> 
> - * All existing ErrorClass values are defined in the qapi-schema.json file
> -
>  === Command Documentation ===
> 
>  There's only one step missing to make "hello-world"'s implementation complete,
>  and that's its documentation in the schema file.
> 
> -This is very important. No QMP command will be accepted in QEMU without proper
> -documentation.
> -
>  There are many examples of such documentation in the schema file already, but
>  here goes "hello-world"'s new entry for qapi/misc.json:
> 
> diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
> index adbc94abb1..430fe1b747 100644
> --- a/docs/interop/qmp-intro.txt
> +++ b/docs/interop/qmp-intro.txt
> @@ -78,7 +78,8 @@ Escape character is '^]'.
>      }
>  }
> 
> -Please, refer to the qapi-schema.json file for a complete command reference.
> +Please refer to docs/interop/qemu-qmp-ref.* for a complete command
> +reference, generated from qapi-schema.json.
> 
>  QMP wiki page
>  -------------
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
  2018-02-12 22:36   ` Eric Blake
  2018-02-13 16:08   ` Marc-Andre Lureau
@ 2018-02-19 19:37   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:37 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:36:05)
> Move qapi-schema.json to qapi/, so it's next to its modules, and all
> files get generated to qapi/, not just the ones generated for modules.
> 
> Consistently name the generated files qapi-MODULE.EXT:
> qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become
> qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch].
> This gets rid of the temporary hacks in scripts/qapi/commands.py and
> scripts/qapi/events.py.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore                                | 16 ++++++------
>  Makefile                                  | 42 +++++++++++++++----------------
>  Makefile.objs                             | 21 ++++++++--------
>  backends/hostmem.c                        |  2 +-
>  docs/devel/qapi-code-gen.txt              | 30 +++++++++++-----------
>  docs/devel/writing-qmp-commands.txt       |  2 +-
>  docs/interop/qmp-intro.txt                |  2 +-
>  hmp.c                                     |  2 +-
>  include/qapi/qmp/qobject.h                |  2 +-
>  include/qapi/visitor.h                    |  2 +-
>  include/qom/object.h                      |  2 +-
>  monitor.c                                 |  6 ++---
>  net/filter-buffer.c                       |  2 +-
>  qapi/misc.json                            |  4 +--
>  qapi-schema.json => qapi/qapi-schema.json | 32 +++++++++++------------
>  qga/Makefile.objs                         |  2 +-
>  qga/commands-posix.c                      |  2 +-
>  qga/commands-win32.c                      |  2 +-
>  qga/commands.c                            |  2 +-
>  qga/main.c                                |  2 +-
>  qom/object.c                              |  2 +-
>  scripts/qapi/commands.py                  |  7 ------
>  scripts/qapi/events.py                    |  9 +------
>  scripts/qapi/introspect.py                |  4 +--
>  scripts/qapi/types.py                     |  6 ++---
>  scripts/qapi/visit.py                     |  6 ++---
>  tests/.gitignore                          |  6 ++---
>  tests/Makefile.include                    | 14 +++++------
>  tests/test-qmp-cmds.c                     |  2 +-
>  tests/test-qmp-event.c                    |  2 +-
>  tests/test-qobject-input-visitor.c        |  6 ++---
>  tpm.c                                     |  1 -
>  ui/cocoa.m                                |  2 +-
>  ui/vnc.c                                  |  2 +-
>  34 files changed, 116 insertions(+), 130 deletions(-)
>  rename qapi-schema.json => qapi/qapi-schema.json (85%)
> 
> diff --git a/.gitignore b/.gitignore
> index 7f162e862f..dabfe6bea8 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -29,8 +29,8 @@
>  /qga/qapi-generated
>  /qapi-generated
>  /qapi-gen-timestamp
> -/qapi-builtin-types.[ch]
> -/qapi-builtin-visit.[ch]
> +/qapi/qapi-builtin-types.[ch]
> +/qapi/qapi-builtin-visit.[ch]
>  /qapi/qapi-commands-block-core.[ch]
>  /qapi/qapi-commands-block.[ch]
>  /qapi/qapi-commands-char.[ch]
> @@ -47,6 +47,7 @@
>  /qapi/qapi-commands-trace.[ch]
>  /qapi/qapi-commands-transaction.[ch]
>  /qapi/qapi-commands-ui.[ch]
> +/qapi/qapi-commands.[ch]
>  /qapi/qapi-events-block-core.[ch]
>  /qapi/qapi-events-block.[ch]
>  /qapi/qapi-events-char.[ch]
> @@ -63,6 +64,8 @@
>  /qapi/qapi-events-trace.[ch]
>  /qapi/qapi-events-transaction.[ch]
>  /qapi/qapi-events-ui.[ch]
> +/qapi/qapi-events.[ch]
> +/qapi/qapi-introspect.[ch]
>  /qapi/qapi-types-block-core.[ch]
>  /qapi/qapi-types-block.[ch]
>  /qapi/qapi-types-char.[ch]
> @@ -79,7 +82,7 @@
>  /qapi/qapi-types-trace.[ch]
>  /qapi/qapi-types-transaction.[ch]
>  /qapi/qapi-types-ui.[ch]
> -/qapi-types.[ch]
> +/qapi/qapi-types.[ch]
>  /qapi/qapi-visit-block-core.[ch]
>  /qapi/qapi-visit-block.[ch]
>  /qapi/qapi-visit-char.[ch]
> @@ -96,11 +99,8 @@
>  /qapi/qapi-visit-trace.[ch]
>  /qapi/qapi-visit-transaction.[ch]
>  /qapi/qapi-visit-ui.[ch]
> -/qapi-visit.[ch]
> -/qapi-event.[ch]
> -/qapi-doc.texi
> -/qmp-commands.[ch]
> -/qmp-introspect.[ch]
> +/qapi/qapi-visit.[ch]
> +/qapi/qapi-doc.texi
>  /qemu-doc.html
>  /qemu-doc.info
>  /qemu-doc.txt
> diff --git a/Makefile b/Makefile
> index 50eb194877..84411ee6ab 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -90,8 +90,8 @@ endif
>  include $(SRC_PATH)/rules.mak
> 
>  GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
> -GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
> -GENERATED_FILES += qapi-types.h qapi-types.c
> +GENERATED_FILES += qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
> +GENERATED_FILES += qapi/qapi-types.h qapi/qapi-types.c
>  GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
>  GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c
>  GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c
> @@ -108,8 +108,8 @@ GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c
>  GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c
>  GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c
>  GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c
> -GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c
> -GENERATED_FILES += qapi-visit.h qapi-visit.c
> +GENERATED_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-visit.c
> +GENERATED_FILES += qapi/qapi-visit.h qapi/qapi-visit.c
>  GENERATED_FILES += qapi/qapi-visit-block-core.h qapi/qapi-visit-block-core.c
>  GENERATED_FILES += qapi/qapi-visit-block.h qapi/qapi-visit-block.c
>  GENERATED_FILES += qapi/qapi-visit-char.h qapi/qapi-visit-char.c
> @@ -126,7 +126,7 @@ GENERATED_FILES += qapi/qapi-visit-tpm.h qapi/qapi-visit-tpm.c
>  GENERATED_FILES += qapi/qapi-visit-trace.h qapi/qapi-visit-trace.c
>  GENERATED_FILES += qapi/qapi-visit-transaction.h qapi/qapi-visit-transaction.c
>  GENERATED_FILES += qapi/qapi-visit-ui.h qapi/qapi-visit-ui.c
> -GENERATED_FILES += qmp-commands.h qmp-commands.c
> +GENERATED_FILES += qapi/qapi-commands.h qapi/qapi-commands.c
>  GENERATED_FILES += qapi/qapi-commands-block-core.h qapi/qapi-commands-block-core.c
>  GENERATED_FILES += qapi/qapi-commands-block.h qapi/qapi-commands-block.c
>  GENERATED_FILES += qapi/qapi-commands-char.h qapi/qapi-commands-char.c
> @@ -143,7 +143,7 @@ GENERATED_FILES += qapi/qapi-commands-tpm.h qapi/qapi-commands-tpm.c
>  GENERATED_FILES += qapi/qapi-commands-trace.h qapi/qapi-commands-trace.c
>  GENERATED_FILES += qapi/qapi-commands-transaction.h qapi/qapi-commands-transaction.c
>  GENERATED_FILES += qapi/qapi-commands-ui.h qapi/qapi-commands-ui.c
> -GENERATED_FILES += qapi-event.h qapi-event.c
> +GENERATED_FILES += qapi/qapi-events.h qapi/qapi-events.c
>  GENERATED_FILES += qapi/qapi-events-block-core.h qapi/qapi-events-block-core.c
>  GENERATED_FILES += qapi/qapi-events-block.h qapi/qapi-events-block.c
>  GENERATED_FILES += qapi/qapi-events-char.h qapi/qapi-events-char.c
> @@ -160,8 +160,8 @@ GENERATED_FILES += qapi/qapi-events-tpm.h qapi/qapi-events-tpm.c
>  GENERATED_FILES += qapi/qapi-events-trace.h qapi/qapi-events-trace.c
>  GENERATED_FILES += qapi/qapi-events-transaction.h qapi/qapi-events-transaction.c
>  GENERATED_FILES += qapi/qapi-events-ui.h qapi/qapi-events-ui.c
> -GENERATED_FILES += qmp-introspect.c qmp-introspect.h
> -GENERATED_FILES += qapi-doc.texi
> +GENERATED_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
> +GENERATED_FILES += qapi/qapi-doc.texi
> 
>  GENERATED_FILES += trace/generated-tcg-tracers.h
> 
> @@ -563,7 +563,7 @@ $(SRC_PATH)/scripts/qapi-gen.py
> 
>  qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \
>  qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \
> -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \
> +qga/qapi-generated/qga-qapi-commands.h qga/qapi-generated/qga-qapi-commands.c \
>  qga/qapi-generated/qga-qapi-doc.texi: \
>  qga/qapi-generated/qapi-gen-timestamp ;
>  qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py)
> @@ -572,7 +572,7 @@ qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-p
>                 "GEN","$(@:%-timestamp=%)")
>         @>$@
> 
> -qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
> +qapi-modules = $(SRC_PATH)/qapi/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
>                 $(SRC_PATH)/qapi/char.json \
>                 $(SRC_PATH)/qapi/crypto.json \
> @@ -588,8 +588,8 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>                 $(SRC_PATH)/qapi/transaction.json \
>                 $(SRC_PATH)/qapi/ui.json
> 
> -qapi-builtin-types.c qapi-builtin-types.h \
> -qapi-types.c qapi-types.h \
> +qapi/qapi-builtin-types.c qapi/qapi-builtin-types.h \
> +qapi/qapi-types.c qapi/qapi-types.h \
>  qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
>  qapi/qapi-types-block.c qapi/qapi-types-block.h \
>  qapi/qapi-types-char.c qapi/qapi-types-char.h \
> @@ -606,8 +606,8 @@ qapi/qapi-types-tpm.c qapi/qapi-types-tpm.h \
>  qapi/qapi-types-trace.c qapi/qapi-types-trace.h \
>  qapi/qapi-types-transaction.c qapi/qapi-types-transaction.h \
>  qapi/qapi-types-ui.c qapi/qapi-types-ui.h \
> -qapi-builtin-visit.c qapi-builtin-visit.h \
> -qapi-visit.c qapi-visit.h \
> +qapi/qapi-builtin-visit.c qapi/qapi-builtin-visit.h \
> +qapi/qapi-visit.c qapi/qapi-visit.h \
>  qapi/qapi-visit-block-core.c qapi/qapi-visit-block-core.h \
>  qapi/qapi-visit-block.c qapi/qapi-visit-block.h \
>  qapi/qapi-visit-char.c qapi/qapi-visit-char.h \
> @@ -624,7 +624,7 @@ qapi/qapi-visit-tpm.c qapi/qapi-visit-tpm.h \
>  qapi/qapi-visit-trace.c qapi/qapi-visit-trace.h \
>  qapi/qapi-visit-transaction.c qapi/qapi-visit-transaction.h \
>  qapi/qapi-visit-ui.c qapi/qapi-visit-ui.h \
> -qmp-commands.h qmp-commands.c \
> +qapi/qapi-commands.h qapi/qapi-commands.c \
>  qapi/qapi-commands-block-core.c qapi/qapi-commands-block-core.h \
>  qapi/qapi-commands-block.c qapi/qapi-commands-block.h \
>  qapi/qapi-commands-char.c qapi/qapi-commands-char.h \
> @@ -641,7 +641,7 @@ qapi/qapi-commands-tpm.c qapi/qapi-commands-tpm.h \
>  qapi/qapi-commands-trace.c qapi/qapi-commands-trace.h \
>  qapi/qapi-commands-transaction.c qapi/qapi-commands-transaction.h \
>  qapi/qapi-commands-ui.c qapi/qapi-commands-ui.h \
> -qapi-event.c qapi-event.h \
> +qapi/qapi-events.c qapi/qapi-events.h \
>  qapi/qapi-events-block-core.c qapi/qapi-events-block-core.h \
>  qapi/qapi-events-block.c qapi/qapi-events-block.h \
>  qapi/qapi-events-char.c qapi/qapi-events-char.h \
> @@ -658,16 +658,16 @@ qapi/qapi-events-tpm.c qapi/qapi-events-tpm.h \
>  qapi/qapi-events-trace.c qapi/qapi-events-trace.h \
>  qapi/qapi-events-transaction.c qapi/qapi-events-transaction.h \
>  qapi/qapi-events-ui.c qapi/qapi-events-ui.h \
> -qmp-introspect.h qmp-introspect.c \
> -qapi-doc.texi: \
> +qapi/qapi-introspect.h qapi/qapi-introspect.c \
> +qapi/qapi-doc.texi: \
>  qapi-gen-timestamp ;
>  qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
>         $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \
> -               -o "." -b $<, \
> +               -o "qapi" -b $<, \
>                 "GEN","$(@:%-timestamp=%)")
>         @>$@
> 
> -QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
> +QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h)
>  $(qga-obj-y): $(QGALIB_GEN)
> 
>  qemu-ga$(EXESUF): $(qga-obj-y) $(COMMON_LDADDS)
> @@ -934,7 +934,7 @@ qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxt
>  qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
>         $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
> 
> -docs/interop/qemu-qmp-qapi.texi: qapi-doc.texi
> +docs/interop/qemu-qmp-qapi.texi: qapi/qapi-doc.texi
>         @cp -p $< $@
> 
>  docs/interop/qemu-ga-qapi.texi: qga/qapi-generated/qga-qapi-doc.texi
> diff --git a/Makefile.objs b/Makefile.objs
> index a7986bbf0b..9aa1024c34 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -2,8 +2,8 @@
>  # Common libraries for tools and emulators
>  stub-obj-y = stubs/ crypto/
>  util-obj-y = util/ qobject/ qapi/
> -util-obj-y += qapi-builtin-types.o
> -util-obj-y += qapi-types.o
> +util-obj-y += qapi/qapi-builtin-types.o
> +util-obj-y += qapi/qapi-types.o
>  util-obj-y += qapi/qapi-types-block-core.o
>  util-obj-y += qapi/qapi-types-block.o
>  util-obj-y += qapi/qapi-types-char.o
> @@ -20,8 +20,8 @@ util-obj-y += qapi/qapi-types-tpm.o
>  util-obj-y += qapi/qapi-types-trace.o
>  util-obj-y += qapi/qapi-types-transaction.o
>  util-obj-y += qapi/qapi-types-ui.o
> -util-obj-y += qapi-builtin-visit.o
> -util-obj-y += qapi-visit.o
> +util-obj-y += qapi/qapi-builtin-visit.o
> +util-obj-y += qapi/qapi-visit.o
>  util-obj-y += qapi/qapi-visit-block-core.o
>  util-obj-y += qapi/qapi-visit-block.o
>  util-obj-y += qapi/qapi-visit-char.o
> @@ -38,7 +38,7 @@ util-obj-y += qapi/qapi-visit-tpm.o
>  util-obj-y += qapi/qapi-visit-trace.o
>  util-obj-y += qapi/qapi-visit-transaction.o
>  util-obj-y += qapi/qapi-visit-ui.o
> -util-obj-y += qapi-event.o
> +util-obj-y += qapi/qapi-events.o
>  util-obj-y += qapi/qapi-events-block-core.o
>  util-obj-y += qapi/qapi-events-block.o
>  util-obj-y += qapi/qapi-events-char.o
> @@ -55,7 +55,7 @@ util-obj-y += qapi/qapi-events-tpm.o
>  util-obj-y += qapi/qapi-events-trace.o
>  util-obj-y += qapi/qapi-events-transaction.o
>  util-obj-y += qapi/qapi-events-ui.o
> -util-obj-y += qmp-introspect.o
> +util-obj-y += qapi/qapi-introspect.o
> 
>  chardev-obj-y = chardev/
> 
> @@ -131,7 +131,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
>  ######################################################################
>  # qapi
> 
> -common-obj-y += qmp-commands.o
> +common-obj-y += qapi/qapi-commands.o
>  common-obj-y += qapi/qapi-commands-block-core.o
>  common-obj-y += qapi/qapi-commands-block.o
>  common-obj-y += qapi/qapi-commands-char.o
> @@ -148,7 +148,7 @@ common-obj-y += qapi/qapi-commands-tpm.o
>  common-obj-y += qapi/qapi-commands-trace.o
>  common-obj-y += qapi/qapi-commands-transaction.o
>  common-obj-y += qapi/qapi-commands-ui.o
> -common-obj-y += qmp-introspect.o
> +common-obj-y += qapi/qapi-introspect.o
>  common-obj-y += qmp.o hmp.o
>  endif
> 
> @@ -171,8 +171,9 @@ target-obj-y += trace/
>  ######################################################################
>  # guest agent
> 
> -# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
> -# by libqemuutil.a.  These should be moved to a separate .json schema.
> +# FIXME: a few definitions from qapi/qapi-types.o and
> +# qapi/qapi-visit.o are needed by libqemuutil.a.  These should be
> +# extracted into a QAPI schema module, or perhaps a separate schema.
>  qga-obj-y = qga/
>  qga-vss-dll-obj-y = qga/
> 
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index 0afaf7160a..1292a9da1e 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -14,7 +14,7 @@
>  #include "sysemu/hostmem.h"
>  #include "hw/boards.h"
>  #include "qapi/error.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/visitor.h"
>  #include "qemu/config-file.h"
>  #include "qom/object_interfaces.h"
> diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
> index ba1dc73298..0c4fc342fe 100644
> --- a/docs/devel/qapi-code-gen.txt
> +++ b/docs/devel/qapi-code-gen.txt
> @@ -647,7 +647,7 @@ name an event 'MAX', since the generator also produces a C enumeration
>  of all event names with a generated _MAX value at the end.  When
>  'data' is also specified, additional info will be included in the
>  event, with similar semantics to a 'struct' expression.  Finally there
> -will be C API generated in qapi-event.h; when called by QEMU code, a
> +will be C API generated in qapi-events.h; when called by QEMU code, a
>  message with timestamp will be emitted on the wire.
> 
>  An example event is:
> @@ -1147,15 +1147,15 @@ declares qmp_COMMAND() that the user must implement.
> 
>  The following files are generated:
> 
> -$(prefix)qmp-commands.c: Command marshal/dispatch functions for each
> -                         QMP command defined in the schema
> +$(prefix)qapi-commands.c: Command marshal/dispatch functions for each
> +                          QMP command defined in the schema
> 
> -$(prefix)qmp-commands.h: Function prototypes for the QMP commands
> -                         specified in the schema
> +$(prefix)qapi-commands.h: Function prototypes for the QMP commands
> +                          specified in the schema
> 
>  Example:
> 
> -    $ cat qapi-generated/example-qmp-commands.h
> +    $ cat qapi-generated/example-qapi-commands.h
>  [Uninteresting stuff omitted...]
> 
>      #ifndef EXAMPLE_QMP_COMMANDS_H
> @@ -1170,7 +1170,7 @@ Example:
>      void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
> 
>      #endif
> -    $ cat qapi-generated/example-qmp-commands.c
> +    $ cat qapi-generated/example-qapi-commands.c
>  [Uninteresting stuff omitted...]
> 
>      static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp)
> @@ -1243,14 +1243,14 @@ qapi_event_send_EVENT().
> 
>  The following files are created:
> 
> -$(prefix)qapi-event.h - Function prototypes for each event type, plus an
> +$(prefix)qapi-events.h - Function prototypes for each event type, plus an
>                          enumeration of all event names
> 
> -$(prefix)qapi-event.c - Implementation of functions to send an event
> +$(prefix)qapi-events.c - Implementation of functions to send an event
> 
>  Example:
> 
> -    $ cat qapi-generated/example-qapi-event.h
> +    $ cat qapi-generated/example-qapi-events.h
>  [Uninteresting stuff omitted...]
> 
>      #ifndef EXAMPLE_QAPI_EVENT_H
> @@ -1273,7 +1273,7 @@ Example:
>      extern const char *const example_QAPIEvent_lookup[];
> 
>      #endif
> -    $ cat qapi-generated/example-qapi-event.c
> +    $ cat qapi-generated/example-qapi-events.c
>  [Uninteresting stuff omitted...]
> 
>      void qapi_event_send_my_event(Error **errp)
> @@ -1305,14 +1305,14 @@ Example:
> 
>  The following files are created:
> 
> -$(prefix)qmp-introspect.c - Defines a string holding a JSON
> +$(prefix)qapi-introspect.c - Defines a string holding a JSON
>                              description of the schema
> 
> -$(prefix)qmp-introspect.h - Declares the above string
> +$(prefix)qapi-introspect.h - Declares the above string
> 
>  Example:
> 
> -    $ cat qapi-generated/example-qmp-introspect.h
> +    $ cat qapi-generated/example-qapi-introspect.h
>  [Uninteresting stuff omitted...]
> 
>      #ifndef EXAMPLE_QMP_INTROSPECT_H
> @@ -1321,7 +1321,7 @@ Example:
>      extern const char example_qmp_schema_json[];
> 
>      #endif
> -    $ cat qapi-generated/example-qmp-introspect.c
> +    $ cat qapi-generated/example-qapi-introspect.c
>  [Uninteresting stuff omitted...]
> 
>      const char example_qmp_schema_json[] = "["
> diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt
> index 50385eff27..9dfc62bf5a 100644
> --- a/docs/devel/writing-qmp-commands.txt
> +++ b/docs/devel/writing-qmp-commands.txt
> @@ -419,7 +419,7 @@ There are a number of things to be noticed:
>     allocated by the implementation. This is so because the QAPI also generates
>     a function to free its types and it cannot distinguish between dynamically
>     or statically allocated strings
> -6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c
> +6. You have to include "qapi/qapi-commands-misc.h" in qemu-timer.c
> 
>  Time to test the new command. Build qemu, run it as described in the "Testing"
>  section and try this:
> diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt
> index 430fe1b747..900d69d612 100644
> --- a/docs/interop/qmp-intro.txt
> +++ b/docs/interop/qmp-intro.txt
> @@ -79,7 +79,7 @@ Escape character is '^]'.
>  }
> 
>  Please refer to docs/interop/qemu-qmp-ref.* for a complete command
> -reference, generated from qapi-schema.json.
> +reference, generated from qapi/qapi-schema.json.
> 
>  QMP wiki page
>  -------------
> diff --git a/hmp.c b/hmp.c
> index c86946866b..1f31de3217 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -28,7 +28,7 @@
>  #include "monitor/qdev.h"
>  #include "qapi/error.h"
>  #include "qapi/opts-visitor.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qapi-commands-block.h"
>  #include "qapi/qapi-commands-char.h"
>  #include "qapi/qapi-commands-migration.h"
> diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
> index a2964fbf25..012439a2e3 100644
> --- a/include/qapi/qmp/qobject.h
> +++ b/include/qapi/qmp/qobject.h
> @@ -32,7 +32,7 @@
>  #ifndef QOBJECT_H
>  #define QOBJECT_H
> 
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
> 
>  struct QObject {
>      QType type;
> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
> index 9e57508446..5b2ed3f202 100644
> --- a/include/qapi/visitor.h
> +++ b/include/qapi/visitor.h
> @@ -15,7 +15,7 @@
>  #ifndef QAPI_VISITOR_H
>  #define QAPI_VISITOR_H
> 
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
> 
>  /*
>   * The QAPI schema defines both a set of C data types, and a QMP wire
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 5b5c016d8f..30db296af4 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -14,7 +14,7 @@
>  #ifndef QEMU_OBJECT_H
>  #define QEMU_OBJECT_H
> 
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>  #include "qemu/queue.h"
> 
>  struct TypeImpl;
> diff --git a/monitor.c b/monitor.c
> index df670f3e15..d0e8d350fd 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -69,14 +69,14 @@
>  #include "exec/exec-all.h"
>  #include "qemu/log.h"
>  #include "qemu/option.h"
> -#include "qmp-commands.h"
>  #include "hmp.h"
>  #include "qemu/thread.h"
>  #include "block/qapi.h"
> +#include "qapi/qapi-commands.h"
> +#include "qapi/qapi-events.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp-event.h"
> -#include "qapi-event.h"
> -#include "qmp-introspect.h"
> +#include "qapi/qapi-introspect.h"
>  #include "sysemu/qtest.h"
>  #include "sysemu/cpus.h"
>  #include "qemu/cutils.h"
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> index 7c487629f9..f7265c50a8 100644
> --- a/net/filter-buffer.c
> +++ b/net/filter-buffer.c
> @@ -13,7 +13,7 @@
>  #include "qemu-common.h"
>  #include "qemu/timer.h"
>  #include "qemu/iov.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qom/object.h"
> 
> diff --git a/qapi/misc.json b/qapi/misc.json
> index 225631bf7d..506f2b9371 100644
> --- a/qapi/misc.json
> +++ b/qapi/misc.json
> @@ -1618,7 +1618,7 @@
>  #
>  # Emitted when background dump has completed
>  #
> -# @result: DumpQueryResult type described in qapi-schema.json.
> +# @result: final dump status
>  #
>  # @error: human-readable error string that provides
>  #         hint on why dump failed. Only presents on failure. The
> @@ -2833,7 +2833,7 @@
>  #
>  # Emitted when guest executes ACPI _OST method.
>  #
> -# @info: ACPIOSTInfo type as described in qapi-schema.json
> +# @info: OSPM Status Indication
>  #
>  # Since: 2.1
>  #
> diff --git a/qapi-schema.json b/qapi/qapi-schema.json
> similarity index 85%
> rename from qapi-schema.json
> rename to qapi/qapi-schema.json
> index 689d06c530..25bce78352 100644
> --- a/qapi-schema.json
> +++ b/qapi/qapi-schema.json
> @@ -76,20 +76,20 @@
>  # included sub-schemas inserted at the first include directive
>  # (subsequent include directives have no effect).  To get a sane and
>  # stable order, it's best to include each sub-schema just once, or
> -# include it first in qapi-schema.json.
> +# include it first right here.
> 
> -{ 'include': 'qapi/common.json' }
> -{ 'include': 'qapi/sockets.json' }
> -{ 'include': 'qapi/run-state.json' }
> -{ 'include': 'qapi/crypto.json' }
> -{ 'include': 'qapi/block.json' }
> -{ 'include': 'qapi/char.json' }
> -{ 'include': 'qapi/net.json' }
> -{ 'include': 'qapi/rocker.json' }
> -{ 'include': 'qapi/tpm.json' }
> -{ 'include': 'qapi/ui.json' }
> -{ 'include': 'qapi/migration.json' }
> -{ 'include': 'qapi/transaction.json' }
> -{ 'include': 'qapi/trace.json' }
> -{ 'include': 'qapi/introspect.json' }
> -{ 'include': 'qapi/misc.json' }
> +{ 'include': 'common.json' }
> +{ 'include': 'sockets.json' }
> +{ 'include': 'run-state.json' }
> +{ 'include': 'crypto.json' }
> +{ 'include': 'block.json' }
> +{ 'include': 'char.json' }
> +{ 'include': 'net.json' }
> +{ 'include': 'rocker.json' }
> +{ 'include': 'tpm.json' }
> +{ 'include': 'ui.json' }
> +{ 'include': 'migration.json' }
> +{ 'include': 'transaction.json' }
> +{ 'include': 'trace.json' }
> +{ 'include': 'introspect.json' }
> +{ 'include': 'misc.json' }
> diff --git a/qga/Makefile.objs b/qga/Makefile.objs
> index 6151378ae4..ed08c5917c 100644
> --- a/qga/Makefile.objs
> +++ b/qga/Makefile.objs
> @@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o
>  qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
>  qga-obj-$(CONFIG_WIN32) += vss-win32.o
>  qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
> -qga-obj-y += qapi-generated/qga-qmp-commands.o
> +qga-obj-y += qapi-generated/qga-qapi-commands.o
> 
>  qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
> diff --git a/qga/commands-posix.c b/qga/commands-posix.c
> index 88807f3c78..417a50ce5f 100644
> --- a/qga/commands-posix.c
> +++ b/qga/commands-posix.c
> @@ -17,7 +17,7 @@
>  #include <sys/wait.h>
>  #include <dirent.h>
>  #include "qga/guest-agent-core.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/queue.h"
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index bedae32957..2d48394748 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -34,7 +34,7 @@
> 
>  #include "qga/guest-agent-core.h"
>  #include "qga/vss-win32.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/queue.h"
> diff --git a/qga/commands.c b/qga/commands.c
> index 6d710dbb20..a64b34ccab 100644
> --- a/qga/commands.c
> +++ b/qga/commands.c
> @@ -12,7 +12,7 @@
> 
>  #include "qemu/osdep.h"
>  #include "qga/guest-agent-core.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/base64.h"
> diff --git a/qga/main.c b/qga/main.c
> index cb434d8c46..f9c83050c5 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -25,7 +25,7 @@
>  #include "qapi/qmp/qstring.h"
>  #include "qga/guest-agent-core.h"
>  #include "qemu/module.h"
> -#include "qga-qmp-commands.h"
> +#include "qga-qapi-commands.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/error.h"
>  #include "qga/channel.h"
> diff --git a/qom/object.c b/qom/object.c
> index 81b4f7ac48..f70a75c308 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -18,7 +18,7 @@
>  #include "qapi/visitor.h"
>  #include "qapi/string-input-visitor.h"
>  #include "qapi/string-output-visitor.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "qapi/qmp/qerror.h"
>  #include "trace.h"
> 
> diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
> index 953449171b..21a7e0dbe6 100644
> --- a/scripts/qapi/commands.py
> +++ b/scripts/qapi/commands.py
> @@ -232,13 +232,6 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>          self._regy = ''
>          self._visited_ret_types = {}
> 
> -    # Temporary HACK:
> -    def _module_basename(self, what, name):
> -        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
> -        if name == self._main_module:
> -            return re.sub(r'qapi-commands', 'qmp-commands', basename)
> -        return basename
> -
>      def _begin_module(self, name):
>          self._visited_ret_types[self._genc] = set()
>          commands = self._module_basename('qapi-commands', name)
> diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> index 5ad6708491..3dc523cf39 100644
> --- a/scripts/qapi/events.py
> +++ b/scripts/qapi/events.py
> @@ -157,20 +157,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
>          self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
>          self._event_names = []
> 
> -    # Temporary HACK:
> -    def _module_basename(self, what, name):
> -        basename = QAPISchemaModularCVisitor._module_basename(self, what, name)
> -        if name == self._main_module:
> -            return re.sub(r'qapi-events', 'qapi-event', basename)
> -        return basename
> -
>      def _begin_module(self, name):
>          types = self._module_basename('qapi-types', name)
>          visit = self._module_basename('qapi-visit', name)
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> -#include "%(prefix)sqapi-event.h"
> +#include "%(prefix)sqapi-events.h"
>  #include "%(visit)s.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
> index f571cc134c..f66c397fb0 100644
> --- a/scripts/qapi/introspect.py
> +++ b/scripts/qapi/introspect.py
> @@ -44,7 +44,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
> 
>      def __init__(self, prefix, unmask):
>          QAPISchemaMonolithicCVisitor.__init__(
> -            self, prefix, 'qmp-introspect',
> +            self, prefix, 'qapi-introspect',
>              ' * QAPI/QMP schema introspection', __doc__)
>          self._unmask = unmask
>          self._schema = None
> @@ -53,7 +53,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
>          self._name_map = {}
>          self._genc.add(mcgen('''
>  #include "qemu/osdep.h"
> -#include "%(prefix)sqmp-introspect.h"
> +#include "%(prefix)sqapi-introspect.h"
> 
>  ''',
>                               prefix=prefix))
> diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
> index 2a3c502cf6..64d9c0fb37 100644
> --- a/scripts/qapi/types.py
> +++ b/scripts/qapi/types.py
> @@ -177,8 +177,8 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>          self._genc.preamble_add(mcgen('''
>  #include "qemu/osdep.h"
>  #include "qapi/dealloc-visitor.h"
> -#include "qapi-builtin-types.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-visit.h"
>  '''))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi/util.h"
> @@ -195,7 +195,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
>  ''',
>                                        types=types, visit=visit))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
>  '''))
> 
>      def visit_begin(self, schema):
> diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
> index de09966643..5d72d8936c 100644
> --- a/scripts/qapi/visit.py
> +++ b/scripts/qapi/visit.py
> @@ -274,11 +274,11 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
>  #include "qapi/error.h"
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  '''))
>          self._genh.preamble_add(mcgen('''
>  #include "qapi/visitor.h"
> -#include "qapi-builtin-types.h"
> +#include "qapi/qapi-builtin-types.h"
> 
>  ''',
>                                        prefix=prefix))
> @@ -295,7 +295,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
>  ''',
>                                        visit=visit, prefix=self._prefix))
>          self._genh.preamble_add(mcgen('''
> -#include "qapi-builtin-visit.h"
> +#include "qapi/qapi-builtin-visit.h"
>  #include "%(types)s.h"
> 
>  ''',
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 2629cfc2f9..18e58b2183 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -60,7 +60,8 @@ test-keyval
>  test-logging
>  test-mul64
>  test-opts-visitor
> -test-qapi-event.[ch]
> +test-qapi-commands.[ch]
> +test-qapi-events.[ch]
>  test-qapi-types.[ch]
>  test-qapi-util
>  test-qapi-visit.[ch]
> @@ -71,11 +72,10 @@ test-qga
>  test-qht
>  test-qht-par
>  test-qmp-cmds
> -test-qmp-commands.[ch]
>  test-qmp-event
>  test-qobject-input-strict
>  test-qobject-input-visitor
> -test-qmp-introspect.[ch]
> +test-qapi-introspect.[ch]
>  test-qobject-output-visitor
>  test-rcu-list
>  test-replication
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 9a21ed7ee9..d71adf3996 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -566,8 +566,8 @@ qapi-schema += unknown-expr-key.json
>  check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema))
> 
>  GENERATED_FILES += tests/test-qapi-types.h tests/test-qapi-visit.h \
> -       tests/test-qmp-commands.h tests/test-qapi-event.h \
> -       tests/test-qmp-introspect.h
> +       tests/test-qapi-commands.h tests/test-qapi-events.h \
> +       tests/test-qapi-introspect.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-qobject.o \
> @@ -592,7 +592,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/tests
>  test-util-obj-y = libqemuutil.a
>  test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
>  test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
> -       tests/test-qapi-event.o tests/test-qmp-introspect.o \
> +       tests/test-qapi-events.o tests/test-qapi-introspect.o \
>         $(test-qom-obj-y)
>  benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
>  test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
> @@ -656,9 +656,9 @@ tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
> 
>  tests/test-qapi-types.c tests/test-qapi-types.h \
>  tests/test-qapi-visit.c tests/test-qapi-visit.h \
> -tests/test-qmp-commands.h tests/test-qmp-commands.c \
> -tests/test-qapi-event.c tests/test-qapi-event.h \
> -tests/test-qmp-introspect.c tests/test-qmp-introspect.h: \
> +tests/test-qapi-commands.h tests/test-qapi-commands.c \
> +tests/test-qapi-events.c tests/test-qapi-events.h \
> +tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \
>  tests/test-qapi-gen-timestamp ;
>  tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py)
>         $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
> @@ -679,7 +679,7 @@ tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
>  tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
>  tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
>  tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
> -tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qmp-commands.o $(test-qapi-obj-y)
> +tests/test-qmp-cmds$(EXESUF): tests/test-qmp-cmds.o tests/test-qapi-commands.o $(test-qapi-obj-y)
>  tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
>  tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
> 
> diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c
> index 24660d0868..5b1cee6912 100644
> --- a/tests/test-qmp-cmds.c
> +++ b/tests/test-qmp-cmds.c
> @@ -3,12 +3,12 @@
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
> -#include "test-qmp-commands.h"
>  #include "qapi/error.h"
>  #include "qemu/module.h"
>  #include "qapi/qobject-input-visitor.h"
>  #include "tests/test-qapi-types.h"
>  #include "tests/test-qapi-visit.h"
> +#include "test-qapi-commands.h"
> 
>  static QmpCommandList qmp_commands;
> 
> diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
> index 5fbe7e551f..31f35b3e66 100644
> --- a/tests/test-qmp-event.c
> +++ b/tests/test-qmp-event.c
> @@ -14,13 +14,13 @@
>  #include "qemu/osdep.h"
> 
>  #include "qemu-common.h"
> -#include "test-qapi-event.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qbool.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp-event.h"
> +#include "test-qapi-events.h"
> 
>  typedef struct TestEventData {
>      QDict *expect;
> diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
> index d3a56bd071..79b1a8cb17 100644
> --- a/tests/test-qobject-input-visitor.c
> +++ b/tests/test-qobject-input-visitor.c
> @@ -24,8 +24,8 @@
>  #include "qapi/qmp/qnum.h"
>  #include "qapi/qmp/qstring.h"
>  #include "qapi/qmp/qjson.h"
> -#include "test-qmp-introspect.h"
> -#include "qmp-introspect.h"
> +#include "test-qapi-introspect.h"
> +#include "qapi/qapi-introspect.h"
> 
>  typedef struct TestInputVisitorData {
>      QObject *obj;
> @@ -1376,7 +1376,7 @@ int main(int argc, char **argv)
>                             NULL, test_visitor_in_fail_alternate);
>      input_visitor_test_add("/visitor/input/fail/union-native-list",
>                             NULL, test_visitor_in_fail_union_native_list);
> -    input_visitor_test_add("/visitor/input/qmp-introspect",
> +    input_visitor_test_add("/visitor/input/qapi-introspect",
>                             NULL, test_visitor_in_qmp_introspect);
> 
>      g_test_run();
> diff --git a/tpm.c b/tpm.c
> index 2db03a09b2..ac580e6d47 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -182,7 +182,6 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
> 
>  /*
>   * Walk the list of active TPM backends and collect information about them
> - * following the schema description in qapi-schema.json.
>   */
>  TPMInfoList *qmp_query_tpm(Error **errp)
>  {
> diff --git a/ui/cocoa.m b/ui/cocoa.m
> index 51db47cd71..de6af6fbb9 100644
> --- a/ui/cocoa.m
> +++ b/ui/cocoa.m
> @@ -32,7 +32,7 @@
>  #include "ui/input.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> -#include "qmp-commands.h"
> +#include "qapi/qapi-commands.h"
>  #include "sysemu/blockdev.h"
>  #include "qemu-version.h"
>  #include <Carbon/Carbon.h>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index d6329c8bd5..20cd9bb63d 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -35,10 +35,10 @@
>  #include "qemu/timer.h"
>  #include "qemu/acl.h"
>  #include "qemu/config-file.h"
> +#include "qapi/qapi-events.h"
>  #include "qapi/error.h"
>  #include "qapi/qapi-commands-ui.h"
>  #include "ui/input.h"
> -#include "qapi-event.h"
>  #include "crypto/hash.h"
>  #include "crypto/tlscredsanon.h"
>  #include "crypto/tlscredsx509.h"
> -- 
> 2.13.6
> 
> 

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

* Re: [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
  2018-02-12 22:47   ` Eric Blake
  2018-02-13 16:12   ` Marc-Andre Lureau
@ 2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:38 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:36:06)
> Fix up the reference to qmp-commands.hx in qmp.c.  Missed in commit
> 5032a16d1d.
> 
> Fix up the reference to qmp-commands.txt in
> docs/xen-save-devices-state.txt.  Missed in commit 4d8bb958fa.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  docs/xen-save-devices-state.txt |  3 +--
>  qmp.c                           | 14 +++++++-------
>  2 files changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt
> index a72ecc8081..1912ecad25 100644
> --- a/docs/xen-save-devices-state.txt
> +++ b/docs/xen-save-devices-state.txt
> @@ -8,8 +8,7 @@ These operations are normally used with migration (see migration.txt),
>  however it is also possible to save the state of all devices to file,
>  without saving the RAM or the block devices of the VM.
> 
> -This operation is called "xen-save-devices-state" (see
> -qmp-commands.txt)
> +The save operation is available as QMP command xen-save-devices-state.
> 
> 
>  The binary format used in the file is the following:
> diff --git a/qmp.c b/qmp.c
> index a8d4eba973..ba82e1df9f 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -147,13 +147,13 @@ VncInfo2List *qmp_query_vnc_servers(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.
> + * qmp_unregister_commands_hack() ensures that QMP command query-spice
> + * exists only #ifdef CONFIG_SPICE.  Necessary for an accurate
> + * query-commands result.  However, the QAPI schema is blissfully
> + * unaware of that, and the QAPI code generator happily generates a
> + * dead qmp_marshal_query_spice() that calls qmp_query_spice().
> + * Provide it one, or else linking fails.  FIXME Educate the QAPI
> + * schema on CONFIG_SPICE.
>   */
>  SpiceInfo *qmp_query_spice(Error **errp)
>  {
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated
  2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
  2018-02-12 22:48   ` Eric Blake
  2018-02-13 16:15   ` Marc-Andre Lureau
@ 2018-02-19 19:38   ` Michael Roth
  2 siblings, 0 replies; 110+ messages in thread
From: Michael Roth @ 2018-02-19 19:38 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: marcandre.lureau, eblake

Quoting Markus Armbruster (2018-02-11 03:36:07)
> We used to generate first test and later QGA QAPI code into
> qapi-generated/.  Commit b93b63f574 moved the test code to tests/.
> Commit 54c2e50205 moved the QGA code to qga/qapi-generated/.  The
> directory has been unused since.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  .gitignore | 1 -
>  Makefile   | 1 -
>  configure  | 1 -
>  3 files changed, 3 deletions(-)
> 
> diff --git a/.gitignore b/.gitignore
> index dabfe6bea8..4055e12ee8 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -27,7 +27,6 @@
>  /libuser
>  /linux-headers/asm
>  /qga/qapi-generated
> -/qapi-generated
>  /qapi-gen-timestamp
>  /qapi/qapi-builtin-types.[ch]
>  /qapi/qapi-builtin-visit.[ch]
> diff --git a/Makefile b/Makefile
> index 84411ee6ab..7eb1ede6f4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -726,7 +726,6 @@ clean:
>         rm -f trace/generated-tracers-dtrace.h*
>         rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
>         rm -f qapi-gen-timestamp
> -       rm -rf qapi-generated
>         rm -rf qga/qapi-generated
>         for d in $(ALL_SUBDIRS); do \
>         if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
> diff --git a/configure b/configure
> index 62562f08cf..f564a1639e 100755
> --- a/configure
> +++ b/configure
> @@ -7015,7 +7015,6 @@ DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-sche
>  DIRS="$DIRS docs docs/interop fsdev scsi"
>  DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
>  DIRS="$DIRS roms/seabios roms/vgabios"
> -DIRS="$DIRS qapi-generated"
>  FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
>  FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
>  FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
> -- 
> 2.13.6
> 

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

* Re: [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
  2018-02-17  0:59   ` Michael Roth
@ 2018-02-23 17:18     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:18 UTC (permalink / raw)
  To: Michael Roth; +Cc: qemu-devel, marcandre.lureau

Michael Roth <mdroth@linux.vnet.ibm.com> writes:

> Quoting Markus Armbruster (2018-02-11 03:35:43)
>> These classes encapsulate accumulating and writing output.
>> 
>> Convert C code generation to QAPIGenC and QAPIGenH.  The conversion is
>> rather shallow: most of the output accumulation is not converted.
>> Left for later.
>> 
>> The indentation machinery uses a single global variable indent_level,
>> even though we generally interleave creation of a .c and its .h.  It
>> should become instance variable of QAPIGenC.  Also left for later.
>> 
>> Documentation generation isn't converted, and QAPIGenDoc isn't used.
>> This will change shortly.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> 2 minor nits below, but in any case:
>
> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
>
>> ---
>>  scripts/qapi-commands.py   | 23 +++++------
>>  scripts/qapi-event.py      | 22 ++++++-----
>>  scripts/qapi-introspect.py | 18 +++++----
>>  scripts/qapi-types.py      | 22 ++++++-----
>>  scripts/qapi-visit.py      | 22 ++++++-----
>>  scripts/qapi.py            | 99 +++++++++++++++++++++++++---------------------
>>  6 files changed, 112 insertions(+), 94 deletions(-)
>> 
>> diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
>> index c3aa52fce1..8d38ade076 100644
>> --- a/scripts/qapi-commands.py
>> +++ b/scripts/qapi-commands.py
>> @@ -260,12 +260,10 @@ blurb = '''
>>   * Schema-defined QAPI/QMP commands
>>  '''
>> 
>> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>> -                            'qmp-marshal.c', 'qmp-commands.h',
>> -                            blurb, __doc__)
>> -
>> -fdef.write(mcgen('''
>> +genc = QAPIGenC(blurb, __doc__)
>> +genh = QAPIGenH(blurb, __doc__)
>> 
>> +genc.add(mcgen('''
>>  #include "qemu/osdep.h"
>>  #include "qemu-common.h"
>>  #include "qemu/module.h"
>> @@ -280,20 +278,23 @@ fdef.write(mcgen('''
>>  #include "%(prefix)sqmp-commands.h"
>> 
>>  ''',
>> -                 prefix=prefix))
>> +               prefix=prefix))
>> 
>> -fdecl.write(mcgen('''
>> +genh.add(mcgen('''
>>  #include "%(prefix)sqapi-types.h"
>>  #include "qapi/qmp/dispatch.h"
>> 
>>  void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
>>  ''',
>> -                  prefix=prefix, c_prefix=c_name(prefix, protect=False)))
>> +               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
>> 
>>  schema = QAPISchema(input_file)
>>  vis = QAPISchemaGenCommandVisitor()
>>  schema.visit(vis)
>> -fdef.write(vis.defn)
>> -fdecl.write(vis.decl)
>> +genc.add(vis.defn)
>> +genh.add(vis.decl)
>> 
>> -close_output(fdef, fdecl)
>> +if do_c:
>> +    genc.write(output_dir, prefix + 'qmp-marshal.c')
>> +if do_h:
>> +    genh.write(output_dir, prefix + 'qmp-commands.h')
>> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
>> index edb9ddb650..bd7a9be3dc 100644
>> --- a/scripts/qapi-event.py
>> +++ b/scripts/qapi-event.py
>> @@ -176,11 +176,10 @@ blurb = '''
>>   * Schema-defined QAPI/QMP events
>>  '''
>> 
>> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>> -                            'qapi-event.c', 'qapi-event.h',
>> -                            blurb, __doc__)
>> +genc = QAPIGenC(blurb, __doc__)
>> +genh = QAPIGenH(blurb, __doc__)
>> 
>> -fdef.write(mcgen('''
>> +genc.add(mcgen('''
>>  #include "qemu/osdep.h"
>>  #include "qemu-common.h"
>>  #include "%(prefix)sqapi-event.h"
>> @@ -191,21 +190,24 @@ fdef.write(mcgen('''
>>  #include "qapi/qmp-event.h"
>> 
>>  ''',
>> -                 prefix=prefix))
>> +               prefix=prefix))
>> 
>> -fdecl.write(mcgen('''
>> +genh.add(mcgen('''
>>  #include "qapi/util.h"
>>  #include "%(prefix)sqapi-types.h"
>> 
>>  ''',
>> -                  prefix=prefix))
>> +               prefix=prefix))
>> 
>>  event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
>> 
>>  schema = QAPISchema(input_file)
>>  vis = QAPISchemaGenEventVisitor()
>>  schema.visit(vis)
>> -fdef.write(vis.defn)
>> -fdecl.write(vis.decl)
>> +genc.add(vis.defn)
>> +genh.add(vis.decl)
>> 
>> -close_output(fdef, fdecl)
>> +if do_c:
>> +    genc.write(output_dir, prefix + 'qapi-event.c')
>> +if do_h:
>> +    genh.write(output_dir, prefix + 'qapi-event.h')
>> diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
>> index ebe8706f41..3d65690fe3 100644
>> --- a/scripts/qapi-introspect.py
>> +++ b/scripts/qapi-introspect.py
>> @@ -181,21 +181,23 @@ blurb = '''
>>   * QAPI/QMP schema introspection
>>  '''
>> 
>> -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
>> -                            'qmp-introspect.c', 'qmp-introspect.h',
>> -                            blurb, __doc__)
>> +genc = QAPIGenC(blurb, __doc__)
>> +genh = QAPIGenH(blurb, __doc__)
>> 
>> -fdef.write(mcgen('''
>> +genc.add(mcgen('''
>>  #include "qemu/osdep.h"
>>  #include "%(prefix)sqmp-introspect.h"
>> 
>>  ''',
>> -                 prefix=prefix))
>> +               prefix=prefix))
>> 
>>  schema = QAPISchema(input_file)
>>  vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
>>  schema.visit(vis)
>> -fdef.write(vis.defn)
>> -fdecl.write(vis.decl)
>> +genc.add(vis.defn)
>> +genh.add(vis.decl)
>> 
>> -close_output(fdef, fdecl)
>> +if do_c:
>> +    genc.write(output_dir, prefix + 'qmp-introspect.c')
>> +if do_h:
>> +    genh.write(output_dir, prefix + 'qmp-introspect.h')
>> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
>> index 4db8424da1..c0ac879beb 100644
>> --- a/scripts/qapi-types.py
>> +++ b/scripts/qapi-types.py
>> @@ -180,7 +180,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
>>          self.decl = ''
>>          self.defn = ''
>>          self._fwdecl = ''
>> -        self._btin = guardstart('QAPI_TYPES_BUILTIN')
>> +        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
>
> Minor nit, but if we compensate for guardstart() change here, shouldn't
> we do the same in QAPISchemaGenVisitVisitor? Both are cosmetic (though
> Visit is in less need since it has extra an extra newline already,
> but changing one and not the other to compensate here makes the patch
> appear less mechanical, and the resulting formatting fix-up gets dropped
> later in the series anyway)

Yes, it's better to keep the two consistent.

>>      def visit_end(self):
>>          self.decl = self._fwdecl + self.decl
>
> <snip>
>
>> +class QAPIGenDoc(QAPIGen):
>> +    def _top(self, fname):
>> +        return (QAPIGen._top(self, fname)
>> +                + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
>
> The whitespace change in
> "qapi/types qapi/visit: Generate built-in stuff into separate files" should
> probably be squashed in here:
>
>  class QAPIGenDoc(QAPIGen):
> +
>      def _top(self, fname):
>          return (QAPIGen._top(self, fname)
>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')

Yes.

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

* Re: [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
  2018-02-12 19:42   ` Eric Blake
@ 2018-02-23 17:20     ` Markus Armbruster
  2018-02-26 20:02       ` Eric Blake
  0 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:20 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>> Whenever qapi-schema.json changes, we run six programs eleven times to
>> update eleven files.  Similar for qga/qapi-schema.json.  This is
>> silly.  Replace the six programs by a single program that spits out
>> all eleven files.
>>
>> The programs become modules in new Python package qapi, along with the
>> helper library.  This requires moving them to scripts/qapi/.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>   .gitignore                                         |  2 +
>>   Makefile                                           | 86 +++++++++----------
>>   docs/devel/qapi-code-gen.txt                       | 97 ++++++++++------------
>>   monitor.c                                          |  2 +-
>>   qapi-schema.json                                   |  2 +-
>>   scripts/qapi-gen.py                                | 41 +++++++++
>>   scripts/qapi/__init__.py                           |  0
>>   scripts/{qapi-commands.py => qapi/commands.py}     | 23 ++---
>>   scripts/{qapi.py => qapi/common.py}                | 18 +---
>>   scripts/{qapi2texi.py => qapi/doc.py}              | 29 ++-----
>>   scripts/{qapi-event.py => qapi/events.py}          | 23 ++---
>>   scripts/{qapi-introspect.py => qapi/introspect.py} | 32 ++-----
>>   scripts/{qapi-types.py => qapi/types.py}           | 34 ++------
>>   scripts/{qapi-visit.py => qapi/visit.py}           | 34 ++------
>>   tests/Makefile.include                             | 56 ++++++-------
>>   tests/qapi-schema/test-qapi.py                     |  4 +-
>>   16 files changed, 193 insertions(+), 290 deletions(-)
>>   create mode 100755 scripts/qapi-gen.py
>>   create mode 100644 scripts/qapi/__init__.py
>>   rename scripts/{qapi-commands.py => qapi/commands.py} (94%)
>>   rename scripts/{qapi.py => qapi/common.py} (99%)
>>   rename scripts/{qapi2texi.py => qapi/doc.py} (92%)
>>   mode change 100755 => 100644
>
> Still forgot mention that the mode bit change was intentional, but not
> worth a respin for just that.
>
>>   rename scripts/{qapi-event.py => qapi/events.py} (92%)
>>   rename scripts/{qapi-introspect.py => qapi/introspect.py} (90%)
>>   rename scripts/{qapi-types.py => qapi/types.py} (90%)
>>   rename scripts/{qapi-visit.py => qapi/visit.py} (92%)
>
> Reviewed-by: Eric Blake <eblake@redhat.com>
>
>> +++ b/docs/devel/qapi-code-gen.txt
>
>> -    $ python scripts/qapi-event.py --output-dir="qapi-generated"
>> -    --prefix="example-" example-schema.json
>>       $ cat qapi-generated/example-qapi-event.h
>>   [Uninteresting stuff omitted...]
>>   @@ -1302,23 +1296,22 @@ Example:
>>       }
>>         const char *const example_QAPIEvent_lookup[] = {
>> -        [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>> +
>> +[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>>           [EXAMPLE_QAPI_EVENT__MAX] = NULL,
>>       };
>
> Looks like our generated code indentation has slightly regressed from
> what we would write by hand, but it's still okay for generated code
> (and the commit message in 5/29 did call that out)

I'd prefer to have this tidied up.

>> +++ b/scripts/qapi-gen.py
>
>> +++ b/scripts/qapi/commands.py
>> @@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
>>   See the COPYING file in the top-level directory.
>>   """
>>   -from qapi import *
>> +from qapi.common import *
>>       def gen_command_decl(name, arg_type, boxed, ret_type):
>> @@ -255,13 +255,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
>>           self._regy += gen_register_command(name, success_response)
>>     -def main(argv):
>> -    (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
>> -
>> -    blurb = '''
>> - * Schema-defined QAPI/QMP commands
>> -'''
>> -
>> +def gen_commands(schema, output_dir, prefix):
>> +    blurb = ' * Schema-defined QAPI/QMP commands'
>
> We discussed whether to make the assignment to blurb be a one-liner in
> an earlier patch, but I'm also fine with the churn you have over the
> course of the series.

I ran out of time, and decided to leave this one as is.

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

* Re: [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
  2018-02-18 22:31   ` Michael Roth
@ 2018-02-23 17:21     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:21 UTC (permalink / raw)
  To: Michael Roth; +Cc: qemu-devel, marcandre.lureau

Michael Roth <mdroth@linux.vnet.ibm.com> writes:

> Quoting Markus Armbruster (2018-02-11 03:35:47)
>> argparse is nicer to use than getopt, and gives us --help almost for
>> free.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  scripts/qapi-gen.py    | 48 ++++++++++++++++++++++++++++++------------------
>>  scripts/qapi/common.py | 43 -------------------------------------------
>>  2 files changed, 30 insertions(+), 61 deletions(-)
>> 
>> diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py
>> index 2100ca1145..e5be484e3e 100755
>> --- a/scripts/qapi-gen.py
>> +++ b/scripts/qapi-gen.py
>> @@ -4,8 +4,11 @@
>>  # This work is licensed under the terms of the GNU GPL, version 2 or later.
>>  # See the COPYING file in the top-level directory.
>> 
>> +from __future__ import print_function
>> +import argparse
>> +import re
>>  import sys
>> -from qapi.common import parse_command_line, QAPISchema
>> +from qapi.common import QAPISchema
>>  from qapi.types import gen_types
>>  from qapi.visit import gen_visit
>>  from qapi.commands import gen_commands
>> @@ -15,26 +18,35 @@ from qapi.doc import gen_doc
>> 
>> 
>>  def main(argv):
>> -    (input_file, output_dir, prefix, opts) = \
>> -        parse_command_line('bu', ['builtins', 'unmask-non-abi-names'])
>> +    parser = argparse.ArgumentParser(
>> +        description='Generate code from a QAPI schema')
>> +    parser.add_argument('-b', '--builtins', action='store_true',
>> +                        help="generate code for built-in types")
>> +    parser.add_argument('-o', '--output_dir', action='store', default='',
>
> Was the change from --output-dir to --output_dir intentional? The former
> seems more consistent.

Editing accident, good catch!

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

* Re: [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
  2018-02-13 15:22     ` Marc-Andre Lureau
@ 2018-02-23 17:22       ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:22 UTC (permalink / raw)
  To: Marc-Andre Lureau; +Cc: Eric Blake, Michael Roth, marcandre, qemu-devel

Marc-Andre Lureau <mlureau@redhat.com> writes:

> Hi
>
> On Mon, Feb 12, 2018 at 8:48 PM, Eric Blake <eblake@redhat.com> wrote:
>> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>>>
>>> A massive number of objects depends on QAPI-generated headers.  In my
>>> "build everything" tree, it's roughly 4800 out of 5100.  This is
>>> particularly annoying when only some of the generated files change,
>>> say for a doc fix.
>>>
>>> Improve qapi-gen.py to touch its output files only if they actually
>>> change.  Rebuild time for a QAPI doc fix drops from many minutes to a
>>> few seconds.  Rebuilds get faster for certain code changes, too.  For
>>> instance, adding a simple QMP event now recompiles less than 200
>>> instead of 4800 objects.  But adding a QAPI type is as bad as ever;
>>> we've clearly got more work to do.
>>>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>> Reviewed-by: Eric Blake <eblake@redhat.com>
>>> ---
>>>   scripts/qapi/common.py | 11 +++++++++--
>>>   1 file changed, 9 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>>> index 8290795dc1..2e58573a39 100644
>>> --- a/scripts/qapi/common.py
>>> +++ b/scripts/qapi/common.py
>>> @@ -1951,9 +1951,16 @@ class QAPIGen(object):
>>>               except os.error as e:
>>>                   if e.errno != errno.EEXIST:
>>>                       raise
>>> -        f = open(os.path.join(output_dir, fname), 'w')
>>> -        f.write(self._top(fname) + self._preamble + self._body
>>> +        fd = os.open(os.path.join(output_dir, fname),
>>> +                     os.O_RDWR | os.O_CREAT, 0666)
>>
>>
>> patchew complained here for mingw; I'm not sure why.
>
> python3 syntax error.
> https://stackoverflow.com/questions/1837874/invalid-token-when-using-octal-numbers

Yes, we need to spell the mode 0o666.

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

* Re: [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
  2018-02-18 23:32   ` Michael Roth
@ 2018-02-23 17:29     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:29 UTC (permalink / raw)
  To: Michael Roth; +Cc: qemu-devel, marcandre.lureau

Michael Roth <mdroth@linux.vnet.ibm.com> writes:

> Quoting Markus Armbruster (2018-02-11 03:35:52)
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi/common.py | 15 +++++++++------
>>  1 file changed, 9 insertions(+), 6 deletions(-)
>> 
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index dce289ae21..cc5a5941dd 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -290,8 +290,12 @@ class QAPISchemaParser(object):
>>                  if not isinstance(include, str):
>>                      raise QAPISemError(info,
>>                                         "Value of 'include' must be a string")
>> -                self._include(include, info, os.path.dirname(self.fname),
>> -                              previously_included)
>> +                exprs_include = self._include(include, info,
>> +                                              os.path.dirname(self.fname),
>> +                                              previously_included)
>> +                if exprs_include:
>> +                    self.exprs.extend(exprs_include.exprs)
>> +                    self.docs.extend(exprs_include.docs)
>>              elif "pragma" in expr:
>>                  self.reject_expr_doc(cur_doc)
>>                  if len(expr) != 1:
>> @@ -334,14 +338,13 @@ class QAPISchemaParser(object):
>> 
>>          # skip multiple include of the same file
>>          if incl_abs_fname in previously_included:
>> -            return
>> +            return None
>> +
>>          try:
>>              fobj = open(incl_fname, 'r')
>>          except IOError as e:
>>              raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname))
>> -        exprs_include = QAPISchemaParser(fobj, previously_included, info)
>> -        self.exprs.extend(exprs_include.exprs)
>> -        self.docs.extend(exprs_include.docs)
>
> minor nit, but the function of _include() seems more appropriately
> described now as _parse_include() or _parse_if_new() or something similar.

I'm open to renaming, but "parse" doesn't really fit.  _include()'s
caller checks syntax, then calls _include() to check semantic
constraints and evaluate the include, then splices in the evaluated
result.

> Maybe it would be more readable to just move the previously_included
> checks into init() and just drop _include() entirely?

Maybe.  But the conditional gets rather long then.

> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

Thanks!

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

* Re: [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree
  2018-02-18 23:57   ` Michael Roth
@ 2018-02-23 17:31     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:31 UTC (permalink / raw)
  To: Michael Roth; +Cc: qemu-devel, marcandre.lureau

Michael Roth <mdroth@linux.vnet.ibm.com> writes:

> Quoting Markus Armbruster (2018-02-11 03:35:53)
>> The parse tree is a list of expressions.  Except include expressions
>> currently get replaced by the included file's parse tree.
>> 
>> Instead of throwing away the include expression, keep it with the file
>> name expanded so you don't have to track the including file's
>> directory to make sense of it.
>> 
>> A future commit will put this include expression to use.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>  scripts/qapi/common.py | 21 +++++++++++++++++----
>>  1 file changed, 17 insertions(+), 4 deletions(-)
>> 
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index cc5a5941dd..6d49709784 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -290,8 +290,11 @@ class QAPISchemaParser(object):
>>                  if not isinstance(include, str):
>>                      raise QAPISemError(info,
>>                                         "Value of 'include' must be a string")
>> -                exprs_include = self._include(include, info,
>> -                                              os.path.dirname(self.fname),
>> +                incl_fname = os.path.join(os.path.dirname(self.fname),
>> +                                          include)
>> +                self.exprs.append({'expr': {'include': incl_fname},
>> +                                   'info': info})
>> +                exprs_include = self._include(include, info, incl_fname,
>>                                                previously_included)
>>                  if exprs_include:
>>                      self.exprs.extend(exprs_include.exprs)
>> @@ -326,8 +329,7 @@ class QAPISchemaParser(object):
>>                  "Documentation for '%s' is not followed by the definition"
>>                  % doc.symbol)
>> 
>> -    def _include(self, include, info, base_dir, previously_included):
>> -        incl_fname = os.path.join(base_dir, include)
>> +    def _include(self, include, info, incl_fname, previously_included):
>>          incl_abs_fname = os.path.abspath(incl_fname)
>>          # catch inclusion cycle
>>          inf = info
>> @@ -893,6 +895,9 @@ def check_exprs(exprs):
>>          info = expr_elem['info']
>>          doc = expr_elem.get('doc')
>> 
>> +        if 'include' in expr:
>> +            continue
>> +
>>          if not doc and doc_required:
>>              raise QAPISemError(info,
>>                                 "Expression missing documentation comment")
>> @@ -931,6 +936,9 @@ def check_exprs(exprs):
>> 
>>      # Try again for hidden UnionKind enum
>>      for expr_elem in exprs:
>> +        if 'include' in expr:
>> +            continue
>> +
>
> Wouldn't this ^
>
>>          expr = expr_elem['expr']
>
> Need to come after this?

D'oh!

>>          if 'union' in expr and not discriminator_find_enum_define(expr):
>>              name = '%sKind' % expr['union']
>> @@ -943,6 +951,9 @@ def check_exprs(exprs):
>> 
>>      # Validate that exprs make sense
>>      for expr_elem in exprs:
>> +        if 'include' in expr:
>> +            continue
>> +
>>          expr = expr_elem['expr']
>
> And here.

Right.  I wonder how this passes tests.

>>          info = expr_elem['info']
>>          doc = expr_elem.get('doc')
>> @@ -1667,6 +1678,8 @@ class QAPISchema(object):
>>                  self._def_command(expr, info, doc)
>>              elif 'event' in expr:
>>                  self._def_event(expr, info, doc)
>> +            elif 'include' in expr:
>> +                pass
>>              else:
>>                  assert False
>> 
>> -- 
>> 2.13.6
>> 

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

* Re: [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation
  2018-02-12 20:34   ` Eric Blake
@ 2018-02-23 17:33     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:33 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>> The include directive permits modular QAPI schemata, but the generated
>> code is monolithic all the same.  To permit generating modular code,
>> the front end needs to pass more information on inclusions to the back
>> ends.  The commit before last added the necessary information to the
>> parse tree.  This commit adds it to the intermediate representation
>> and its QAPISchemaVisitor.  A later commit will use this to to
>> generate modular code.
>>
>> New entity QAPISchemaInclude represents inclusions.  Call new visitor
>> method visit_include() for it, so visitors can see the sub-modules a
>> module includes.
>>
>> Note that unlike other entities, QAPISchemaInclude has no name, and is
>> therefore not added to entity_dict.
>>
>> New QAPISchemaEntity attribute @module names the entity's source file.
>> Call new visitor method visit_module() when it changes during a visit,
>> so visitors can keep track of the module being visited.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>> @@ -1479,16 +1497,19 @@ class QAPISchema(object):
>>           self._entity_dict = {}
>>           self._predefining = True
>>           self._def_predefineds()
>> -        self._predefining = False
>>           self._def_exprs(exprs)
>>           self.check()
>
> Why does self._predfining not need to be toggled anymore?  Do we even
> need this variable any more...
>
>>
>>      def _def_entity(self, ent):
>>          # Only the predefined types are allowed to not have info
>>          assert ent.info or self._predefining
>> -        assert ent.name not in self._entity_dict
>
> ...and/or is this assert now worthless?
>
>
>> +++ b/tests/qapi-schema/comments.out
>> @@ -1,4 +1,5 @@
>>   object q_empty
>>   enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
>>       prefix QTYPE
>> +module comments.json
>>   enum Status ['good', 'bad', 'ugly']
>
> Based on the generated output, it looks like you can tell whether you
> are in the predefining stage by not having any module at all; the
> first visit_module call is what flips the switch that everything else
> is defined by a module and must therefore have associated info.

Editing accident.  I started down the road you described, decided I lack
the time to reach its end, then failed to back out completely.

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

* Re: [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
  2018-02-19 15:52   ` Michael Roth
@ 2018-02-23 17:35     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:35 UTC (permalink / raw)
  To: Michael Roth; +Cc: qemu-devel, marcandre.lureau

Michael Roth <mdroth@linux.vnet.ibm.com> writes:

> Quoting Markus Armbruster (2018-02-11 03:35:57)
>> The use of QAPIGen is rather shallow so far: most of the output
>> accumulation is not converted.  Take the next step: convert output
>> accumulation in the code-generating visitor classes.  Helper functions
>> outside these classes are not converted.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  scripts/qapi/commands.py   | 71 ++++++++++++++++------------------------
>>  scripts/qapi/common.py     | 13 ++++++++
>>  scripts/qapi/doc.py        | 74 ++++++++++++++++++++----------------------
>>  scripts/qapi/events.py     | 55 ++++++++++++-------------------
>>  scripts/qapi/introspect.py | 56 +++++++++++++-------------------
>>  scripts/qapi/types.py      | 81 +++++++++++++++++++---------------------------
>>  scripts/qapi/visit.py      | 80 +++++++++++++++++++--------------------------
>>  7 files changed, 188 insertions(+), 242 deletions(-)
>> 
>
> <snip>
>
>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>> index 29d98ca934..31d2f73e7e 100644
>> --- a/scripts/qapi/common.py
>> +++ b/scripts/qapi/common.py
>> @@ -2049,3 +2049,16 @@ class QAPIGenDoc(QAPIGen):
>>      def _top(self, fname):
>>          return (QAPIGen._top(self, fname)
>>                  + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
>> +
>> +
>> +class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
>> +
>> +    def __init__(self, prefix, what, blurb, pydoc):
>> +        self._prefix = prefix
>> +        self._what = what
>> +        self._genc = QAPIGenC(blurb, pydoc)
>> +        self._genh = QAPIGenH(blurb, pydoc)
>> +
>> +    def write(self, output_dir):
>> +        self._genc.write(output_dir, self._prefix + self._what + '.c')
>> +        self._genh.write(output_dir, self._prefix + self._what + '.h')
>
> minor nit: since subclasses of QAPISchemaVisitor and
> QAPISchemaMonolithicCVisitor all rely on .write() now, should we declare it
> in the abstract QAPISchemaVisitor?

Perhaps.  If they had more in common, the case for an abstract super
class would be clearer.

> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

Thanks!

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

* Re: [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
  2018-02-12 21:44   ` Eric Blake
@ 2018-02-23 17:36     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:36 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>> Linking code from multiple separate QAPI schemata into the same
>> program is possible, but involves some weirdness around built-in
>> types:
>>
>> * We generate code for built-in types into .c only with option
>>    --builtins.  The user is responsible for generating code for exactly
>>    one QAPI schema per program with --builtins.
>>
>> * We generate code for built-in types into .h regardless of
>>    --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN.  Because all
>>    copies of this code are exactly the same, including any combination
>>    of these headers works.
>>
>> Replace this contraption by something more conventional: generate code
>> for built-in types into their very own files: qapi-builtin-types.c,
>> qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but
>> only with --builtins.  Obey --output-dir, but ignore --prefix for
>> them.
>>
>> Make qapi-types.h include qapi-builtin-types.h.  With multiple
>> schemata you now have multiple qapi-types.[ch], but only one
>> qapi-builtin-types.[ch].  Same for qapi-visit.[ch] and
>> qapi-builtin-visit.[ch].
>>
>> Bonus: if all you need is built-in stuff, you can include a much
>> smaller header.  To be exploited shortly.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>> @@ -2046,6 +2046,7 @@ class QAPIGenH(QAPIGenC):
>>       class QAPIGenDoc(QAPIGen):
>> +
>>       def _top(self, fname):
>>           return (QAPIGen._top(self, fname)
>>                   + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
>
> Does this hunk belong in an earlier patch?

Yes: PATCH 05.

> Otherwise,
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

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

* Re: [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module
  2018-02-12 22:06   ` Eric Blake
@ 2018-02-23 17:41     ` Markus Armbruster
  2018-02-26 22:39       ` Eric Blake
  0 siblings, 1 reply; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:41 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:36 AM, Markus Armbruster wrote:
>> Our qapi-schema.json is composed of modules connected by include
>> directives, but the generated code is monolithic all the same: one
>> qapi-types.h with all the types, one qapi-visit.h with all the
>> visitors, and so forth.  These monolithic headers get included all
>> over the place.  In my "build everything" tree, adding a QAPI type
>> recompiles about 4800 out of 5100 objects.
>>
>> We wouldn't write such monolithic headers by hand.  It stands to
>> reason that we shouldn't generate them, either.
>>
>> Split up generated qapi-types.h to mirror the schema's modular
>> structure: one header per module.  Name the main module's header
>> qapi-types.h, and sub-module D/B.json's header D/qapi-types-B.h.
>>
>> Mirror the schema's includes in the headers, so that qapi-types.h gets
>> you everything exactly as before.  If you need less, you can include
>> one or more of the sub-module headers.  To be exploited shortly.
>>
>> Split up qapi-types.c, qapi-visit.h, qapi-visit.c, qmp-commands.h,
>> qmp-commands.c, qapi-event.h, qapi-event.c the same way.
>> qmp-introspect.h, qmp-introspect.c and qapi.texi remain monolithic.
>
> Make sense.
>
>>
>> The split of qmp-commands.c duplicates static helper function
>> qmp_marshal_output_str() in qapi-commands-char.c and
>> qapi-commands-misc.c.  This happens when commands returning the same
>> type occur in multiple modules.  Not worth avoiding.
>
> As long as it is static, and neither .c file includes the other, we're
> fine (gdb may have a harder time figuring out which copy to put a
> breakpoint on, but that's not too terrible).
>
>>
>> Since I'm going to rename qapi-event.[ch] to qapi-events.[ch], and
>> qmp-commands.[ch] to qapi-commands.[ch], name the shards that way
>> already, to reduce churn.  This requires temporary hacks in
>> commands.py and events.py.  They'll go away with the rename.
>
> The planned rename makes sense; prepping now is fine.
>
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>   .gitignore               |  60 ++++++++++++++++++++++++
>>   Makefile                 | 120 +++++++++++++++++++++++++++++++++++++++++++++++
>>   Makefile.objs            |  65 ++++++++++++++++++++++++-
>>   scripts/qapi/commands.py |  35 +++++++++-----
>>   scripts/qapi/common.py   |  21 +++++++--
>>   scripts/qapi/events.py   |  19 ++++++--
>>   6 files changed, 300 insertions(+), 20 deletions(-)
>>
>> diff --git a/.gitignore b/.gitignore
>> index 9477a08b6b..42c57998fd 100644
>> --- a/.gitignore
>> +++ b/.gitignore
>> @@ -31,7 +31,67 @@
>>   /qapi-gen-timestamp
>>   /qapi-builtin-types.[ch]
>>   /qapi-builtin-visit.[ch]
>> +/qapi/qapi-commands-block-core.[ch]
>> +/qapi/qapi-commands-block.[ch]
>
> Is it worth using a glob instead of specific patterns, as in:
>
> /qapi/qapi-commands-*.[ch]
>
> Maybe being precise doesn't hurt, if we aren't adding sub-modules all
> that often; but being generous with a glob makes it less likely that a
> future module addition will forget to update .gitignore.

We should simply ditch building in-tree.  I wanted to post patches for
that for quite some time.

>> +++ b/Makefile
>> @@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak
>>   GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
>>   GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
>>   GENERATED_FILES += qapi-types.h qapi-types.c
>> +GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
>
> For the makefile, I'd suggest using an intermediate list of module
> names, and then using make string operations to expand it into larger
> lists, to cut down on the repetition.  Something like (untested):
>
> QAPI_MODULES = block-core block char common ...
> GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
> .c,$(QAPI_MODULES))
> GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
> .h,$(QAPI_MODULES))

I did it the stupid way to save time.  Improvements welcome :)

>> @@ -525,10 +585,70 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
>>     qapi-builtin-types.c qapi-builtin-types.h \
>>   qapi-types.c qapi-types.h \
>> +qapi/qapi-types-block-core.c qapi/qapi-types-block-core.h \
>> +qapi/qapi-types-block.c qapi/qapi-types-block.h \
>
> And repeating the list of filenames; again, an intermediate variable
> would let you do:
>
> QAPI_GENERATED_FILES = ...
> GENERATED_FILES += $(QAPI_GENERATED_FILES)
>
> $(QAPI_GENERATED_FILES): ...
>
>>   qmp-introspect.h qmp-introspect.c \
>>   qapi-doc.texi: \
>>   qapi-gen-timestamp ;
>
> Not only does it cut down on the repetition, but it will make adding a
> future module easier.
>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 2813e984fd..7a55d45669 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -3,8 +3,56 @@
>>   stub-obj-y = stubs/ crypto/
>>   util-obj-y = util/ qobject/ qapi/
>>   util-obj-y += qapi-builtin-types.o
>> +util-obj-y += qapi-types.o
>> +util-obj-y += qapi/qapi-types-block-core.o
>
> Perhaps this can also exploit make text manipulation?
>
> Otherwise looks good.

Thanks!

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

* Re: [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers
  2018-02-12 22:13   ` Eric Blake
@ 2018-02-23 17:47     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:47 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:36 AM, Markus Armbruster wrote:
>> In my "build everything" tree, a change to the types in
>> qapi-schema.json triggers a recompile of about 4800 out of 5100
>> objects.
>>
>> The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h,
>> qapi-types.h.  Each of these headers still includes all its shards.
>> Reduce compile time by including just the shards we actually need.
>>
>> To illustrate the benefits: adding a type to qapi/migration.json now
>> recompiles some 2300 instead of 4800 objects.  The next commit will
>> improve it further.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>   backends/cryptodev.c             |  1 -
>>   backends/hostmem.c               |  3 ++-
>
> How did you determine which shards to include where? Remove all
> shards, try compiling, and see what fails, then add back in the right
> includes? Or was it scripted somehow?  (Trying to figure out, in case
> I have to rebase this patch)

Remove the monolithic include, fix compilation failures in my
"everything" and my mingw configuration.  Additionally, verify headers
don't regress with an embarrassingly crude script (appended).

By "regress" I mean headers need more headers to be included first than
before.  Ideally, *no* headers need to be included first, but we aren't
there (yet?).

>> +++ b/block/crypto.c
>> @@ -24,9 +24,9 @@
>>   #include "sysemu/block-backend.h"
>>   #include "crypto/block.h"
>>   #include "qapi/opts-visitor.h"
>> +#include "qapi/qapi-visit-crypto.h"
>>   #include "qapi/qmp/qdict.h"
>>   #include "qapi/qobject-input-visitor.h"
>> -#include "qapi-visit.h"
>>   #include "qapi/error.h"
>
> Any rhyme or reason to the resulting include order that I should be
> looking for (we aren't alphabetical in general, but if your changes
> were trying to honor a particular pattern among the few affected
> lines, that's useful to know).

Sane headers can be include in any order.  Ours are almost sane, which
prevents me from wholesale sorting.  I still try to keep things locally
sorted.  Feel free not to bother :)

>> +++ b/scripts/qapi/commands.py
>
> The non-mechanical portion of the patch :)
>
>> @@ -241,6 +241,9 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>>         def _begin_module(self, name):
>>           self._visited_ret_types[self._genc] = set()
>> +        commands = self._module_basename('qapi-commands', name)
>> +        types = self._module_basename('qapi-types', name)
>> +        visit = self._module_basename('qapi-visit', name)
>>           self._genc.add(mcgen('''
>>   #include "qemu/osdep.h"
>>   #include "qemu-common.h"
>> @@ -251,18 +254,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
>>   #include "qapi/qobject-input-visitor.h"
>>   #include "qapi/dealloc-visitor.h"
>>   #include "qapi/error.h"
>> -#include "%(prefix)sqapi-types.h"
>> -#include "%(prefix)sqapi-visit.h"
>> -#include "%(prefix)sqmp-commands.h"
>> +#include "%(visit)s.h"
>> +#include "%(commands)s.h"
>>     ''',
>> -                             prefix=self._prefix))
>> +                             commands=commands, visit=visit))
>>           self._genh.add(mcgen('''
>> -#include "%(prefix)sqapi-types.h"
>> +#include "%(types)s.h"
>>   #include "qapi/qmp/dispatch.h"
>>     ''',
>> -                             prefix=self._prefix))
>> +                             types=types))
>
> Makes sense.
>
> The compiler will catch anything we did wrong.
>
> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!


#!/bin/sh
git-log -1 --oneline | cat

make -C bld qapi-types.h

cat >t.c <<EOF
#include "qemu/osdep.h"
#ifdef H
#include H
#endif
EOF

x=
for d in target/*
do
    t=${d#target/}
    bt=`ls -d bld/$t*-softmmu 2>/dev/null | head -n 1`
    [ "$bt" ] || continue
    h=`git-ls-files include/hw/$t`
    x="$x|include/hw/$t"
    cd $bt
    for i in $h
    do
	echo "= $i ="
	gcc -I/home/armbru/work/qemu/tcg -I/home/armbru/work/qemu/tcg/$t -I/home/armbru/work/qemu/tcg/i386 -I/home/armbru/work/qemu/linux-headers -I/home/armbru/work/qemu/bld/linux-headers -I. -I/home/armbru/work/qemu -I/home/armbru/work/qemu/include -I/home/armbru/work/qemu -I. -I/usr/include/pixman-1   -DHAS_LIBSSH2_SFTP_FSYNC -fPIE -DPIE -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common  -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong  -I/usr/include/p11-kit-1     -I/usr/include/libpng16  -I/usr/include/spice-server -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/spice-1  -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4  -I/usr/include/libusb-1.0    -I../linux-headers -I.. -I/home/armbru/work/qemu/$d -DNEED_CPU_H -I/home/armbru/work/qemu/include -MMD -MP -MT t.o -MF ./t.d -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include  -g   -c -o t.o /home/armbru/work/qemu/t.c -H -DH='"'$i'"'
    done
    cd - >/dev/null
done

x=${x#|}
h=`git-ls-files include | egrep -v "$x"`
cd bld
for i in $h
do
    echo "= $i ="
    gcc -I/home/armbru/work/qemu/tcg -I/home/armbru/work/qemu/tcg/i386 -I/home/armbru/work/qemu/linux-headers -I/home/armbru/work/qemu/bld/linux-headers -I. -I/home/armbru/work/qemu -I/home/armbru/work/qemu/include -I/home/armbru/work/qemu -I. -I/usr/include/pixman-1   -DHAS_LIBSSH2_SFTP_FSYNC -fPIE -DPIE -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common  -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong  -I/usr/include/p11-kit-1     -I/usr/include/libpng16  -I/usr/include/spice-server -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/spice-1  -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4  -I/usr/include/libusb-1.0   -I/home/armbru/work/qemu/tests -MMD -MP -MT t.o -MF ./t.d -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include  -g   -c -o t.o /home/armbru/work/qemu/t.c -H -DH='"'$i'"'
done
exit 0

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

* Re: [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json
  2018-02-12 22:26   ` Eric Blake
@ 2018-02-23 17:50     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:50 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:36 AM, Markus Armbruster wrote:
>> The previous commit improved compile time by including less of the
>> generated QAPI headers.  This is impossible for stuff defined directly
>> in qapi-schema.json, because that ends up in headers that that pull in
>> everything.
>>
>> Move everything but include directives from qapi-schema.json to new
>> sub-module qapi/misc.json, then include just the "misc" shard where
>> possible.
>>
>> It's not possible everywhere, except:
>
> Odd wording, did you mean one of:
>
> It's possible everywhere, except:
> It's almost possible everywhere, except:

The former.

>> * monitor.c needs qmp-command.h to get qmp_init_marshall()
>
> s/marshall/marshal/

Yes.

>> * monitor.c, ui/vnc.c and the generated qapi-event-FOO.c need
>>    qapi-event.h to get enum QAPIEvent
>>
>> Perhaps we'll get rid of those some other day.
>>
>> Adding a type to qapi/migration.json now recompiles some 120 instead
>> of 2300 out of 5100 objects.
>
> Getting better :)
>
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>   .gitignore                         |    4 +
>>   Makefile                           |    9 +
>>   Makefile.objs                      |    4 +
>>   arch_init.c                        |    2 +-
>>   balloon.c                          |    2 +-
>>   block/iscsi.c                      |    2 +-
>>   cpus.c                             |    2 +-
>>   dump.c                             |    4 +-
>>   hmp.c                              |   10 +-
>>   hw/acpi/core.c                     |    2 +-
>>   hw/acpi/cpu.c                      |    2 +-
>>   hw/acpi/memory_hotplug.c           |    2 +-
>>   hw/acpi/vmgenid.c                  |    2 +-
>>   hw/core/qdev.c                     |    2 +-
>>   hw/i386/xen/xen-hvm.c              |    2 +-
>>   hw/ipmi/ipmi.c                     |    2 +-
>>   hw/pci/pci-stub.c                  |    2 +-
>>   hw/pci/pci.c                       |    2 +-
>>   hw/ppc/spapr_rtc.c                 |    2 +-
>>   hw/s390x/s390-skeys.c              |    2 +-
>>   hw/timer/mc146818rtc.c             |    4 +-
>>   hw/virtio/virtio-balloon.c         |    2 +-
>>   hw/watchdog/watchdog.c             |    2 +-
>>   include/hw/qdev-properties.h       |    3 +-
>>   include/monitor/monitor.h          |    2 +-
>>   include/sysemu/arch_init.h         |    2 +-
>>   include/sysemu/balloon.h           |    2 +-
>>   include/sysemu/dump.h              |    2 +-
>>   include/sysemu/hostmem.h           |    2 +-
>>   include/sysemu/replay.h            |    3 +-
>>   iothread.c                         |    2 +-
>>   migration/savevm.c                 |    3 +-
>>   numa.c                             |    4 +-
>
> Mostly mechanical,
>
>>   qapi-schema.json                   | 3098 +-----------------------------------
>>   qapi/misc.json                     | 3090 +++++++++++++++++++++++++++++++++++
>
> A huge move of content (git won't flag it as a rename, though ;(
>
> But why is the new file smaller than what was removed from the old
> file? Let's see...[1]
>
>>   qapi/run-state.json                |   10 +
>>   qdev-monitor.c                     |    2 +-
>>   qmp.c                              |    4 +-
>>   stubs/uuid.c                       |    2 +-
>>   stubs/vmgenid.c                    |    2 +-
>>   stubs/xen-hvm.c                    |    2 +-
>>   target/arm/monitor.c               |    3 +-
>>   target/i386/cpu.c                  |    4 +-
>>   tests/qmp-test.c                   |    3 +-
>>   tests/test-qobject-input-visitor.c |    2 +-
>>   tests/test-visitor-serialization.c |    1 -
>>   ui/gtk.c                           |    2 +-
>>   util/qemu-config.c                 |    2 +-
>>   vl.c                               |    4 +-
>>   49 files changed, 3181 insertions(+), 3144 deletions(-)
>>   create mode 100644 qapi/misc.json
>
> Huge email, but reviewing is not too hard.
>
>>
>> diff --git a/.gitignore b/.gitignore
>> index 42c57998fd..7f162e862f 100644
>> --- a/.gitignore
>> +++ b/.gitignore
>> @@ -38,6 +38,7 @@
>>   /qapi/qapi-commands-crypto.[ch]
>>   /qapi/qapi-commands-introspect.[ch]
>>   /qapi/qapi-commands-migration.[ch]
>> +/qapi/qapi-commands-misc.[ch]
>
> If my comments on the earlier patch result in a glob here, you
> wouldn't need these changes.
>
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -99,6 +99,7 @@ GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c
>>   GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c
>>   GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c
>>   GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c
>> +GENERATED_FILES += qapi/qapi-types-misc.h qapi/qapi-types-misc.c
>>   GENERATED_FILES += qapi/qapi-types-net.h qapi/qapi-types-net.c
>>   GENERATED_FILES += qapi/qapi-types-rocker.h qapi/qapi-types-rocker.c
>>   GENERATED_FILES += qapi/qapi-types-run-state.h qapi/qapi-types-run-state.c
>> @@ -116,6 +117,7 @@ GENERATED_FILES += qapi/qapi-visit-common.h qapi/qapi-visit-common.c
>>   GENERATED_FILES += qapi/qapi-visit-crypto.h qapi/qapi-visit-crypto.c
>>   GENERATED_FILES += qapi/qapi-visit-introspect.h qapi/qapi-visit-introspect.c
>>   GENERATED_FILES += qapi/qapi-visit-migration.h qapi/qapi-visit-migration.c
>> +GENERATED_FILES += qapi/qapi-visit-misc.h qapi/qapi-visit-misc.c
>
> And again, my comments about using intermediate variables and make
> text substitution would result in less duplication here.
>
>> +++ b/Makefile.objs
>> @@ -11,6 +11,7 @@ util-obj-y += qapi/qapi-types-common.o
>>   util-obj-y += qapi/qapi-types-crypto.o
>>   util-obj-y += qapi/qapi-types-introspect.o
>>   util-obj-y += qapi/qapi-types-migration.o
>> +util-obj-y += qapi/qapi-types-misc.o
>
> and possibly here too.
>
>> +++ b/hmp.c
>> @@ -23,13 +23,21 @@
>>   #include "qemu/config-file.h"
>>   #include "qemu/option.h"
>>   #include "qemu/timer.h"
>> -#include "qmp-commands.h"
>>   #include "qemu/sockets.h"
>>   #include "monitor/monitor.h"
>>   #include "monitor/qdev.h"
>>   #include "qapi/error.h"
>>   #include "qapi/opts-visitor.h"
>>   #include "qapi-builtin-visit.h"
>> +#include "qapi/qapi-commands-block.h"
>> +#include "qapi/qapi-commands-char.h"
>> +#include "qapi/qapi-commands-migration.h"
>> +#include "qapi/qapi-commands-misc.h"
>> +#include "qapi/qapi-commands-net.h"
>> +#include "qapi/qapi-commands-rocker.h"
>> +#include "qapi/qapi-commands-run-state.h"
>> +#include "qapi/qapi-commands-tpm.h"
>> +#include "qapi/qapi-commands-ui.h"
>
> Well, not every file gets a smaller list of includes ;)
>
>> +++ b/qapi-schema.json
>> @@ -92,3100 +92,4 @@
>>   { 'include': 'qapi/transaction.json' }
>>   { 'include': 'qapi/trace.json' }
>>   { 'include': 'qapi/introspect.json' }
>> -
>> -##
>> -# = Miscellanea
>> -##
>
>> -# Since: 2.11
>> -##
>> -{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
>> +{ 'include': 'qapi/misc.json' }
>
> [1] Conflict magnet. We'd better be prepared for some rebasing to get
> this patch series through.  See what the last item is here...
>
>> diff --git a/qapi/misc.json b/qapi/misc.json
>> new file mode 100644
>> index 0000000000..225631bf7d
>> --- /dev/null
>> +++ b/qapi/misc.json
>> @@ -0,0 +1,3090 @@
>> +# -*- Mode: Python -*-
>> +#
>> +
>
> Should we be thinking about copyright/license statements in the QAPI
> submodule files?  But that's a topic for another series.
>
>
>> +# Since: 2.9
>> +##
>> +{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
>> diff --git a/qapi/run-state.json b/qapi/run-state.json
>
> [1] ...and oops - you already hit one of those
> conflicts. watchdog-set-action disappeared in the move.  Or did it?
> [2]
>
>> index bca46a8785..a27c3c2a93 100644
>> --- a/qapi/run-state.json
>> +++ b/qapi/run-state.json
>> @@ -283,6 +283,16 @@
>>     'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
>>               'inject-nmi' ] }
>>   +
>> +##
>> +# @watchdog-set-action:
>> +#
>> +# Set watchdog action
>> +#
>> +# Since: 2.11
>> +##
>> +{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
>> +
>
> [2] Oh, you MOVED it to a different file.  Let's fix that separately,
> so that THIS patch can be just 1-1 file motion, not 1-N (making
> rebasing easier).

Okay.

>>   ##
>>   # @GUEST_PANICKED:
>>   #
>> diff --git a/qdev-monitor.c b/qdev-monitor.c
>> index 846238175f..b8f6bc3f7e 100644
>> --- a/qdev-monitor.c
>
> Looks reasonable, but not quite ready for my R-b until v3.

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

* Re: [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
  2018-02-12 22:36   ` Eric Blake
@ 2018-02-23 17:51     ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-02-23 17:51 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, marcandre.lureau, mdroth

Eric Blake <eblake@redhat.com> writes:

> On 02/11/2018 03:36 AM, Markus Armbruster wrote:
>> Move qapi-schema.json to qapi/, so it's next to its modules, and all
>> files get generated to qapi/, not just the ones generated for modules.
>>
>> Consistently name the generated files qapi-MODULE.EXT:
>> qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become
>> qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch].
>> This gets rid of the temporary hacks in scripts/qapi/commands.py and
>> scripts/qapi/events.py.
>
> Ah, so my parallel series that proposed naming the file
> qapi/qmp-schema.qapi gets interesting, with your patch favoring the
> qapi- naming everywhere.  I'll have to think about how much (or
> little) of my series to rebase on top of this (I like my notion of
> renaming to the .qapi suffix, though, as we really are using files
> that aren't JSON, but only resemble it).
>
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>
>> +++ b/.gitignore
>> @@ -29,8 +29,8 @@
>>   /qga/qapi-generated
>>   /qapi-generated
>>   /qapi-gen-timestamp
>> -/qapi-builtin-types.[ch]
>> -/qapi-builtin-visit.[ch]
>> +/qapi/qapi-builtin-types.[ch]
>> +/qapi/qapi-builtin-visit.[ch]
>
> Might be some interesting churn if you like my idea of using globs for
> easier maintenance of this file.
>
>> +++ b/tpm.c
>> @@ -182,7 +182,6 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
>>     /*
>>    * Walk the list of active TPM backends and collect information about them
>> - * following the schema description in qapi-schema.json.
>>    */
>
> Should the overall comment keep the trailing '.'?

I'm fine either way.

> Reviewed-by: Eric Blake <eblake@redhat.com>

Thanks!

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

* Re: [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
  2018-02-23 17:20     ` Markus Armbruster
@ 2018-02-26 20:02       ` Eric Blake
  0 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-26 20:02 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, marcandre.lureau, mdroth

On 02/23/2018 11:20 AM, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
> 
>> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>>> Whenever qapi-schema.json changes, we run six programs eleven times to
>>> update eleven files.  Similar for qga/qapi-schema.json.  This is
>>> silly.  Replace the six programs by a single program that spits out
>>> all eleven files.
>>>
>>> The programs become modules in new Python package qapi, along with the
>>> helper library.  This requires moving them to scripts/qapi/.
>>>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---

>>> +++ b/docs/devel/qapi-code-gen.txt

>>>    @@ -1302,23 +1296,22 @@ Example:
>>>        }
>>>          const char *const example_QAPIEvent_lookup[] = {
>>> -        [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>>> +
>>> +[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
>>>            [EXAMPLE_QAPI_EVENT__MAX] = NULL,
>>>        };
>>
>> Looks like our generated code indentation has slightly regressed from
>> what we would write by hand, but it's still okay for generated code
>> (and the commit message in 5/29 did call that out)
> 
> I'd prefer to have this tidied up.

Actually, we currently output with good indentation, but with different 
text altogether:

const QEnumLookup example_QAPIEvent_lookup = {
     .array = (const char *const[]) {
         [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
     },
     .size = EXAMPLE_QAPI_EVENT__MAX
};

I'm fixing that up as part of prepping this series for PULL.


>>> +def gen_commands(schema, output_dir, prefix):
>>> +    blurb = ' * Schema-defined QAPI/QMP commands'
>>
>> We discussed whether to make the assignment to blurb be a one-liner in
>> an earlier patch, but I'm also fine with the churn you have over the
>> course of the series.
> 
> I ran out of time, and decided to leave this one as is.

It wasn't too difficult (although the ripple effects hit 3 other 
patches), so I did this as well.

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

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

* Re: [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module
  2018-02-23 17:41     ` Markus Armbruster
@ 2018-02-26 22:39       ` Eric Blake
  0 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-26 22:39 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-devel, marcandre.lureau, mdroth

On 02/23/2018 11:41 AM, Markus Armbruster wrote:


>>> +++ b/Makefile
>>> @@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak
>>>    GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
>>>    GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
>>>    GENERATED_FILES += qapi-types.h qapi-types.c
>>> +GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c
>>
>> For the makefile, I'd suggest using an intermediate list of module
>> names, and then using make string operations to expand it into larger
>> lists, to cut down on the repetition.  Something like (untested):
>>
>> QAPI_MODULES = block-core block char common ...
>> GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
>> .c,$(QAPI_MODULES))
>> GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
>> .h,$(QAPI_MODULES))
> 
> I did it the stupid way to save time.  Improvements welcome :)


>>> +++ b/Makefile.objs
>>> @@ -3,8 +3,56 @@
>>>    stub-obj-y = stubs/ crypto/
>>>    util-obj-y = util/ qobject/ qapi/
>>>    util-obj-y += qapi-builtin-types.o
>>> +util-obj-y += qapi-types.o
>>> +util-obj-y += qapi/qapi-types-block-core.o
>>
>> Perhaps this can also exploit make text manipulation?
>>
>> Otherwise looks good.
> 
> Thanks!

At this point, I'll take your patch as-is, and worry about improvements 
as followups.

Reviewed-by: Eric Blake <eblake@redhat.com>

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

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

* [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (29 preceding siblings ...)
  2018-02-11 10:16 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code no-reply
@ 2018-02-26 22:57 ` Eric Blake
  2018-02-26 23:10   ` Eric Blake
  2018-02-27 14:19 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Eric Blake
  31 siblings, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-26 22:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: mprivozn, armbru, marcandre.lureau, mdroth, Paolo Bonzini

Commit f0df84c6 added watchdog-set-action in the main qapi-schema.json,
but it belongs better in qapi/run-state.json alongside the definition
of WatchdogAction.

Signed-off-by: Eric Blake <eblake@redhat.com>
---

Based on my review of 24/29, I'm inserting this patch right before
rebasing that one onto master.

 qapi-schema.json    | 9 ---------
 qapi/run-state.json | 9 +++++++++
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 05cc58e121e..93912e804ab 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3180,12 +3180,3 @@
 # Since: 2.9
 ##
 { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
-
-##
-# @watchdog-set-action:
-#
-# Set watchdog action
-#
-# Since: 2.11
-##
-{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index bca46a8785f..3924357fef4 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -283,6 +283,15 @@
   'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
             'inject-nmi' ] }

+##
+# @watchdog-set-action:
+#
+# Set watchdog action
+#
+# Since: 2.11
+##
+{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
 ##
 # @GUEST_PANICKED:
 #
-- 
2.14.3

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

* Re: [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file
  2018-02-26 22:57 ` [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file Eric Blake
@ 2018-02-26 23:10   ` Eric Blake
  0 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-26 23:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: mdroth, mprivozn, Paolo Bonzini, armbru, marcandre.lureau

On 02/26/2018 04:57 PM, Eric Blake wrote:
> Commit f0df84c6 added watchdog-set-action in the main qapi-schema.json,
> but it belongs better in qapi/run-state.json alongside the definition
> of WatchdogAction.

I'm adding:

The command was written prior to commit 0e201d34 creating the latter 
file, even though it was merged after.

> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> 
> Based on my review of 24/29, I'm inserting this patch right before
> rebasing that one onto master.
> 
>   qapi-schema.json    | 9 ---------
>   qapi/run-state.json | 9 +++++++++
>   2 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 05cc58e121e..93912e804ab 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3180,12 +3180,3 @@
>   # Since: 2.9
>   ##
>   { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
> -
> -##
> -# @watchdog-set-action:
> -#
> -# Set watchdog action
> -#
> -# Since: 2.11
> -##
> -{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
> diff --git a/qapi/run-state.json b/qapi/run-state.json
> index bca46a8785f..3924357fef4 100644
> --- a/qapi/run-state.json
> +++ b/qapi/run-state.json
> @@ -283,6 +283,15 @@
>     'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
>               'inject-nmi' ] }
> 
> +##
> +# @watchdog-set-action:
> +#
> +# Set watchdog action
> +#
> +# Since: 2.11
> +##
> +{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
> +
>   ##
>   # @GUEST_PANICKED:
>   #
> 

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

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

* Re: [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code
  2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
                   ` (30 preceding siblings ...)
  2018-02-26 22:57 ` [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file Eric Blake
@ 2018-02-27 14:19 ` Eric Blake
  31 siblings, 0 replies; 110+ messages in thread
From: Eric Blake @ 2018-02-27 14:19 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> Our qapi-schema.json is composed of modules connected by include
> directives, but the generated code is monolithic all the same: one
> qapi-types.h with all the types, one qapi-visit.h with all the
> visitors, and so forth.  These monolithic headers get included all
> over the place.  In my "build everything" tree, adding a QAPI type
> recompiles about 4800 out of 5100 objects.
> 
> We wouldn't write such monolithic headers by hand.  It stands to
> reason that we shouldn't generate them, either.
> 
> This series' basic idea is to split up generated headers to mirror the
> schema's modular structure: one header per module.  That way, you can
> include just what you need.
> 
> The compile-time improvements can be massive.  Before this series, any
> QAPI schema change recompiles some 4800 out of 5100 objects in my
> "build everything" tree.  Afterwards, adding a type to
> qapi/migration.json recompiles a bit over 100, and a documentation
> change no longer recompiles anything.
> 
> Related: Marc-André's 'unit' pragma proposal.  That's a different way
> to split off parts of the generated code, motivated by the desire to
> use poisoned identifiers such as TARGET_I386.  I noted in my review of
> v3 that I "can either accept it, or come up with a better solution."
> This is my attempt at a better solution.  It's a bit more ambitious,
> and thus more useful (I hope).  The pragma has one theoretical
> advantage, though: you can modularize the generated output in
> different ways than the input.  The patches using don't do that,
> however.
> 

>   186 files changed, 1556 insertions(+), 1352 deletions(-)

I've posted a staging version of this at:

http://repo.or.cz/qemu/ericb.git qapi

Barring any last-minute comments, or a need to rebase for other branches 
going in, I'll submit a pull request later today.


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

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

* Re: [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
  2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
  2018-02-17  1:29   ` Michael Roth
@ 2018-02-27 15:53   ` Eric Blake
  2018-02-27 16:01     ` Daniel P. Berrangé
  1 sibling, 1 reply; 110+ messages in thread
From: Eric Blake @ 2018-02-27 15:53 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: mdroth, marcandre.lureau

On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> The next commit will introduce a common driver program for all
> generators.  The generators need to be modules for that.  qapi2texi.py
> already is.  Make the other generators follow suit.
> 
> The changes are actually trivial.  Obvious in the diffs once you view
> them with whitespace changes ignored.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   scripts/qapi-commands.py   | 43 ++++++++++++++++++--------------
>   scripts/qapi-event.py      | 43 ++++++++++++++++++--------------
>   scripts/qapi-introspect.py | 54 ++++++++++++++++++++++------------------
>   scripts/qapi-types.py      | 56 ++++++++++++++++++++++-------------------
>   scripts/qapi-visit.py      | 62 +++++++++++++++++++++++++---------------------
>   5 files changed, 143 insertions(+), 115 deletions(-)

Urgh. One annoyance of this patch is that if you switch to another 
branch without the patch, leftover .pyc files in the source tree can 
cause weird errors until you 'rm -f scripts/qapi/*.pyc':

$ make -j3
   GEN     config-host.h
   GEN     qmp-commands.h
   GEN     qapi-types.h
Traceback (most recent call last):
   File "/home/eblake/qemu/scripts/qapi-commands.py", line 225, in <module>
     class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
NameError: name 'QAPISchemaVisitor' is not defined
Traceback (most recent call last):
   File "/home/eblake/qemu/scripts/qapi-types.py", line 168, in <module>
     class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
NameError: name 'QAPISchemaVisitor' is not defined
make: *** [Makefile:522: qapi-types.h] Error 1
make: *** Waiting for unfinished jobs....
make: *** [Makefile:537: qmp-commands.h] Error 1

Not a show-stopper, but annoying when toggling between branches.

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

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

* Re: [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
  2018-02-27 15:53   ` Eric Blake
@ 2018-02-27 16:01     ` Daniel P. Berrangé
  2018-04-13 12:49       ` Markus Armbruster
  0 siblings, 1 reply; 110+ messages in thread
From: Daniel P. Berrangé @ 2018-02-27 16:01 UTC (permalink / raw)
  To: Eric Blake; +Cc: Markus Armbruster, qemu-devel, marcandre.lureau, mdroth

On Tue, Feb 27, 2018 at 09:53:22AM -0600, Eric Blake wrote:
> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
> > The next commit will introduce a common driver program for all
> > generators.  The generators need to be modules for that.  qapi2texi.py
> > already is.  Make the other generators follow suit.
> > 
> > The changes are actually trivial.  Obvious in the diffs once you view
> > them with whitespace changes ignored.
> > 
> > Signed-off-by: Markus Armbruster <armbru@redhat.com>
> > Reviewed-by: Eric Blake <eblake@redhat.com>
> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >   scripts/qapi-commands.py   | 43 ++++++++++++++++++--------------
> >   scripts/qapi-event.py      | 43 ++++++++++++++++++--------------
> >   scripts/qapi-introspect.py | 54 ++++++++++++++++++++++------------------
> >   scripts/qapi-types.py      | 56 ++++++++++++++++++++++-------------------
> >   scripts/qapi-visit.py      | 62 +++++++++++++++++++++++++---------------------
> >   5 files changed, 143 insertions(+), 115 deletions(-)
> 
> Urgh. One annoyance of this patch is that if you switch to another branch
> without the patch, leftover .pyc files in the source tree can cause weird
> errors until you 'rm -f scripts/qapi/*.pyc':

Pehaps make our build system set  PYTHONDONTWRITEBYTECODE=1  env variable

  https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

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

* Re: [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
  2018-02-27 16:01     ` Daniel P. Berrangé
@ 2018-04-13 12:49       ` Markus Armbruster
  0 siblings, 0 replies; 110+ messages in thread
From: Markus Armbruster @ 2018-04-13 12:49 UTC (permalink / raw)
  To: Daniel P. Berrangé; +Cc: Eric Blake, mdroth, marcandre.lureau, qemu-devel

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Tue, Feb 27, 2018 at 09:53:22AM -0600, Eric Blake wrote:
>> On 02/11/2018 03:35 AM, Markus Armbruster wrote:
>> > The next commit will introduce a common driver program for all
>> > generators.  The generators need to be modules for that.  qapi2texi.py
>> > already is.  Make the other generators follow suit.
>> > 
>> > The changes are actually trivial.  Obvious in the diffs once you view
>> > them with whitespace changes ignored.
>> > 
>> > Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> > Reviewed-by: Eric Blake <eblake@redhat.com>
>> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> > ---
>> >   scripts/qapi-commands.py   | 43 ++++++++++++++++++--------------
>> >   scripts/qapi-event.py      | 43 ++++++++++++++++++--------------
>> >   scripts/qapi-introspect.py | 54 ++++++++++++++++++++++------------------
>> >   scripts/qapi-types.py      | 56 ++++++++++++++++++++++-------------------
>> >   scripts/qapi-visit.py      | 62 +++++++++++++++++++++++++---------------------
>> >   5 files changed, 143 insertions(+), 115 deletions(-)
>> 
>> Urgh. One annoyance of this patch is that if you switch to another branch
>> without the patch, leftover .pyc files in the source tree can cause weird
>> errors until you 'rm -f scripts/qapi/*.pyc':
>
> Pehaps make our build system set  PYTHONDONTWRITEBYTECODE=1  env variable
>
>   https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE

We already have configure put PYTHON=python -B into config-host.mak.

I still manage to litter my tree with .pyc files...

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

end of thread, other threads:[~2018-04-13 12:49 UTC | newest]

Thread overview: 110+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
2018-02-12 16:55   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
2018-02-12 19:40   ` Eric Blake
2018-02-16 22:53   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
2018-02-12 16:59   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-16 22:56   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc Markus Armbruster
2018-02-17  0:59   ` Michael Roth
2018-02-23 17:18     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some Markus Armbruster
2018-02-17  1:22   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
2018-02-17  1:29   ` Michael Roth
2018-02-27 15:53   ` Eric Blake
2018-02-27 16:01     ` Daniel P. Berrangé
2018-04-13 12:49       ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
2018-02-12 19:42   ` Eric Blake
2018-02-23 17:20     ` Markus Armbruster
2018-02-26 20:02       ` Eric Blake
2018-02-18 22:16   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
2018-02-12 19:44   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-18 22:31   ` Michael Roth
2018-02-23 17:21     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
2018-02-12 19:48   ` Eric Blake
2018-02-13 15:22     ` Marc-Andre Lureau
2018-02-23 17:22       ` Markus Armbruster
2018-02-18 22:43   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages Markus Armbruster
2018-02-18 23:11   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs Markus Armbruster
2018-02-18 23:13   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
2018-02-12 19:52   ` Eric Blake
2018-02-18 23:17   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
2018-02-12 19:56   ` Eric Blake
2018-02-18 23:32   ` Michael Roth
2018-02-23 17:29     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
2018-02-12 20:03   ` Eric Blake
2018-02-18 23:57   ` Michael Roth
2018-02-23 17:31     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
2018-02-12 20:06   ` Eric Blake
2018-02-19  0:01   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation Markus Armbruster
2018-02-12 20:34   ` Eric Blake
2018-02-23 17:33     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
2018-02-12 20:56   ` Eric Blake
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19  0:21   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
2018-02-12 21:06   ` Eric Blake
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19 15:52   ` Michael Roth
2018-02-23 17:35     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
2018-02-12 21:44   ` Eric Blake
2018-02-23 17:36     ` Markus Armbruster
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19 19:30   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames Markus Armbruster
2018-02-19 18:18   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module Markus Armbruster
2018-02-12 22:06   ` Eric Blake
2018-02-23 17:41     ` Markus Armbruster
2018-02-26 22:39       ` Eric Blake
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
2018-02-12 22:13   ` Eric Blake
2018-02-23 17:47     ` Markus Armbruster
2018-02-13 15:54   ` Marc-Andre Lureau
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json Markus Armbruster
2018-02-12 22:26   ` Eric Blake
2018-02-23 17:50     ` Markus Armbruster
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
2018-02-12 22:27   ` Eric Blake
2018-02-13 16:00   ` Marc-Andre Lureau
2018-02-19 19:33   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
2018-02-12 22:29   ` Eric Blake
2018-02-13 16:03   ` Marc-Andre Lureau
2018-02-19 19:35   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
2018-02-12 22:36   ` Eric Blake
2018-02-23 17:51     ` Markus Armbruster
2018-02-13 16:08   ` Marc-Andre Lureau
2018-02-19 19:37   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
2018-02-12 22:47   ` Eric Blake
2018-02-13 16:12   ` Marc-Andre Lureau
2018-02-19 19:38   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
2018-02-12 22:48   ` Eric Blake
2018-02-13 16:15   ` Marc-Andre Lureau
2018-02-19 19:38   ` Michael Roth
2018-02-11 10:16 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code no-reply
2018-02-26 22:57 ` [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file Eric Blake
2018-02-26 23:10   ` Eric Blake
2018-02-27 14:19 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Eric Blake

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.