QAPI patches for 2018-07-03
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbO+InAAoJEDhwtADrkYZTtsQQAI2IEFWwsIWtjh+JO2xWHjTC sXrzD2m8g50xledX1mKgQdA9NujvrSreQBFEgXvOEz65K8hl1HIqNp9C4NeOPUGn vVxDGRrMz1rGRrBXXM9mf2v3ZSMw0mVAmpBzQ2lO/fPsGEAThJ4451c0mHiMhBXi Ez2v3Qod597ITWCG73DccCN7ehl+3HCpqAyvBjVjtolmnt0h4oefqb8OV1l59kl3 dywlnEoMcLq80uznAkkCnQ89yZR6ygrZIYfyMynpkTo4quf/ZB8eHF8Au4Jyynby 1cAPAs0tfjmfvSpSEGvWyhmuu8jKm9pGnby7Me18HV/dkyNWzQWWMpzWpYHxiu41 fa0SpBpw4g112SaeNOOt0g+SDpcdtvTheWmyPbzSL1yTDJ2NTppbl2zpNo9BHY3X jFSXpNi74RTB4KDXx+t/QXJepo3f35dTOOoOvodhT4EHzTIkPQoalKbKZij6zDHo CoBRrJQ8WQIxaYuiYHCDdRxTBbq44XbW30rWDnjmUBcLW6uMuUOiZxUh+n2GQjP7 dEZel23zslqPdFexnTX32miIfkiHABKWIr7EzZ4NC8P/0U8McKD/lxGP8IHrs9Lo D8UYgfOGse2w5MWXCxSwq+VY5aFPasYrpVpi31gnCzLtJ9Q8qBMoqIGdyFKHzxXj qTvkP1iSHnXjSsq0KryZ =uZ84 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2018-07-03' into staging QAPI patches for 2018-07-03 # gpg: Signature made Tue 03 Jul 2018 21:52:55 BST # gpg: using RSA key 3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2018-07-03: qapi: add conditions to SPICE type/commands/events on the schema qapi: add conditions to VNC type/commands/events on the schema qapi: add 'If:' section to generated documentation qapi-types: add #if conditions to types & visitors qapi/events: add #if conditions to events qapi/commands: add #if conditions to commands qapi-introspect: add preprocessor conditions to generated QLit qapi-introspect: modify to_qlit() to append ',' on level > 0 qapi: add #if/#endif helpers qapi: mcgen() shouldn't indent # lines qapi: add 'ifcond' to visitor methods qapi: leave the ifcond attribute undefined until check() qapi: pass 'if' condition into QAPISchemaEntity objects qapi: add 'if' to top-level expressions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5dafaf4fbc
@ -744,6 +744,35 @@ Example: Red Hat, Inc. controls redhat.com, and may therefore add a
|
|||||||
downstream command __com.redhat_drive-mirror.
|
downstream command __com.redhat_drive-mirror.
|
||||||
|
|
||||||
|
|
||||||
|
=== Configuring the schema ===
|
||||||
|
|
||||||
|
The 'struct', 'enum', 'union', 'alternate', 'command' and 'event'
|
||||||
|
top-level expressions can take an 'if' key. Its value must be a string
|
||||||
|
or a list of strings. A string is shorthand for a list containing just
|
||||||
|
that string. The code generated for the top-level expression will then
|
||||||
|
be guarded by #if COND for each COND in the list.
|
||||||
|
|
||||||
|
Example: a conditional struct
|
||||||
|
|
||||||
|
{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': ['defined(CONFIG_FOO)', 'defined(HAVE_BAR)'] }
|
||||||
|
|
||||||
|
gets its generated code guarded like this:
|
||||||
|
|
||||||
|
#if defined(CONFIG_FOO)
|
||||||
|
#if defined(HAVE_BAR)
|
||||||
|
... generated code ...
|
||||||
|
#endif /* defined(HAVE_BAR) */
|
||||||
|
#endif /* defined(CONFIG_FOO) */
|
||||||
|
|
||||||
|
Please note that you are responsible to ensure that the C code will
|
||||||
|
compile with an arbitrary combination of conditions, since the
|
||||||
|
generators are unable to check it at this point.
|
||||||
|
|
||||||
|
The presence of 'if' keys in the schema is reflected through to the
|
||||||
|
introspection output depending on the build configuration.
|
||||||
|
|
||||||
|
|
||||||
== Client JSON Protocol introspection ==
|
== Client JSON Protocol introspection ==
|
||||||
|
|
||||||
Clients of a Client JSON Protocol commonly need to figure out what
|
Clients of a Client JSON Protocol commonly need to figure out what
|
||||||
|
@ -426,6 +426,7 @@ STEXI
|
|||||||
Show which guest mouse is receiving events.
|
Show which guest mouse is receiving events.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
#if defined(CONFIG_VNC)
|
||||||
{
|
{
|
||||||
.name = "vnc",
|
.name = "vnc",
|
||||||
.args_type = "",
|
.args_type = "",
|
||||||
@ -433,6 +434,7 @@ ETEXI
|
|||||||
.help = "show the vnc server status",
|
.help = "show the vnc server status",
|
||||||
.cmd = hmp_info_vnc,
|
.cmd = hmp_info_vnc,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@item info vnc
|
@item info vnc
|
||||||
|
9
hmp.c
9
hmp.c
@ -616,6 +616,7 @@ void hmp_info_blockstats(Monitor *mon, const QDict *qdict)
|
|||||||
qapi_free_BlockStatsList(stats_list);
|
qapi_free_BlockStatsList(stats_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VNC
|
||||||
/* Helper for hmp_info_vnc_clients, _servers */
|
/* Helper for hmp_info_vnc_clients, _servers */
|
||||||
static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
|
static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
|
||||||
const char *name)
|
const char *name)
|
||||||
@ -703,6 +704,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
|
|||||||
qapi_free_VncInfo2List(info2l);
|
qapi_free_VncInfo2List(info2l);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SPICE
|
#ifdef CONFIG_SPICE
|
||||||
void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
||||||
@ -1772,12 +1774,14 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
|
|||||||
hmp_handle_error(mon, &err);
|
hmp_handle_error(mon, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VNC
|
||||||
static void hmp_change_read_arg(void *opaque, const char *password,
|
static void hmp_change_read_arg(void *opaque, const char *password,
|
||||||
void *readline_opaque)
|
void *readline_opaque)
|
||||||
{
|
{
|
||||||
qmp_change_vnc_password(password, NULL);
|
qmp_change_vnc_password(password, NULL);
|
||||||
monitor_read_command(opaque, 1);
|
monitor_read_command(opaque, 1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void hmp_change(Monitor *mon, const QDict *qdict)
|
void hmp_change(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
@ -1788,6 +1792,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
|||||||
BlockdevChangeReadOnlyMode read_only_mode = 0;
|
BlockdevChangeReadOnlyMode read_only_mode = 0;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_VNC
|
||||||
if (strcmp(device, "vnc") == 0) {
|
if (strcmp(device, "vnc") == 0) {
|
||||||
if (read_only) {
|
if (read_only) {
|
||||||
monitor_printf(mon,
|
monitor_printf(mon,
|
||||||
@ -1802,7 +1807,9 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
qmp_change("vnc", target, !!arg, arg, &err);
|
qmp_change("vnc", target, !!arg, arg, &err);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (read_only) {
|
if (read_only) {
|
||||||
read_only_mode =
|
read_only_mode =
|
||||||
qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
|
qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
|
||||||
|
@ -1191,9 +1191,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
|
|||||||
*/
|
*/
|
||||||
static void qmp_unregister_commands_hack(void)
|
static void qmp_unregister_commands_hack(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SPICE
|
|
||||||
qmp_unregister_command(&qmp_commands, "query-spice");
|
|
||||||
#endif
|
|
||||||
#ifndef CONFIG_REPLICATION
|
#ifndef CONFIG_REPLICATION
|
||||||
qmp_unregister_command(&qmp_commands, "xen-set-replication");
|
qmp_unregister_command(&qmp_commands, "xen-set-replication");
|
||||||
qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
|
qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
|
||||||
|
@ -320,6 +320,7 @@
|
|||||||
##
|
##
|
||||||
{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
|
{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
|
||||||
'base': 'ChardevCommon' }
|
'base': 'ChardevCommon' }
|
||||||
|
# TODO: 'if': 'defined(CONFIG_SPICE)'
|
||||||
|
|
||||||
##
|
##
|
||||||
# @ChardevSpicePort:
|
# @ChardevSpicePort:
|
||||||
@ -332,6 +333,7 @@
|
|||||||
##
|
##
|
||||||
{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
|
{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
|
||||||
'base': 'ChardevCommon' }
|
'base': 'ChardevCommon' }
|
||||||
|
# TODO: 'if': 'defined(CONFIG_SPICE)'
|
||||||
|
|
||||||
##
|
##
|
||||||
# @ChardevVC:
|
# @ChardevVC:
|
||||||
@ -385,8 +387,10 @@
|
|||||||
'testdev': 'ChardevCommon',
|
'testdev': 'ChardevCommon',
|
||||||
'stdio' : 'ChardevStdio',
|
'stdio' : 'ChardevStdio',
|
||||||
'console': 'ChardevCommon',
|
'console': 'ChardevCommon',
|
||||||
'spicevmc' : 'ChardevSpiceChannel',
|
'spicevmc': 'ChardevSpiceChannel',
|
||||||
'spiceport' : 'ChardevSpicePort',
|
# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
|
||||||
|
'spiceport': 'ChardevSpicePort',
|
||||||
|
# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
|
||||||
'vc' : 'ChardevVC',
|
'vc' : 'ChardevVC',
|
||||||
'ringbuf': 'ChardevRingbuf',
|
'ringbuf': 'ChardevRingbuf',
|
||||||
# next one is just for compatibility
|
# next one is just for compatibility
|
||||||
|
75
qapi/ui.json
75
qapi/ui.json
@ -118,7 +118,8 @@
|
|||||||
{ 'struct': 'SpiceBasicInfo',
|
{ 'struct': 'SpiceBasicInfo',
|
||||||
'data': { 'host': 'str',
|
'data': { 'host': 'str',
|
||||||
'port': 'str',
|
'port': 'str',
|
||||||
'family': 'NetworkAddressFamily' } }
|
'family': 'NetworkAddressFamily' },
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SpiceServerInfo:
|
# @SpiceServerInfo:
|
||||||
@ -131,7 +132,8 @@
|
|||||||
##
|
##
|
||||||
{ 'struct': 'SpiceServerInfo',
|
{ 'struct': 'SpiceServerInfo',
|
||||||
'base': 'SpiceBasicInfo',
|
'base': 'SpiceBasicInfo',
|
||||||
'data': { '*auth': 'str' } }
|
'data': { '*auth': 'str' },
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SpiceChannel:
|
# @SpiceChannel:
|
||||||
@ -156,7 +158,8 @@
|
|||||||
{ 'struct': 'SpiceChannel',
|
{ 'struct': 'SpiceChannel',
|
||||||
'base': 'SpiceBasicInfo',
|
'base': 'SpiceBasicInfo',
|
||||||
'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
|
'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
|
||||||
'tls': 'bool'} }
|
'tls': 'bool'},
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SpiceQueryMouseMode:
|
# @SpiceQueryMouseMode:
|
||||||
@ -175,7 +178,8 @@
|
|||||||
# Since: 1.1
|
# Since: 1.1
|
||||||
##
|
##
|
||||||
{ 'enum': 'SpiceQueryMouseMode',
|
{ 'enum': 'SpiceQueryMouseMode',
|
||||||
'data': [ 'client', 'server', 'unknown' ] }
|
'data': [ 'client', 'server', 'unknown' ],
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SpiceInfo:
|
# @SpiceInfo:
|
||||||
@ -212,7 +216,8 @@
|
|||||||
{ 'struct': 'SpiceInfo',
|
{ 'struct': 'SpiceInfo',
|
||||||
'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
|
'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
|
||||||
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
|
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
|
||||||
'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']} }
|
'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']},
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @query-spice:
|
# @query-spice:
|
||||||
@ -257,7 +262,8 @@
|
|||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
{ 'command': 'query-spice', 'returns': 'SpiceInfo' }
|
{ 'command': 'query-spice', 'returns': 'SpiceInfo',
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SPICE_CONNECTED:
|
# @SPICE_CONNECTED:
|
||||||
@ -282,7 +288,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'SPICE_CONNECTED',
|
{ 'event': 'SPICE_CONNECTED',
|
||||||
'data': { 'server': 'SpiceBasicInfo',
|
'data': { 'server': 'SpiceBasicInfo',
|
||||||
'client': 'SpiceBasicInfo' } }
|
'client': 'SpiceBasicInfo' },
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SPICE_INITIALIZED:
|
# @SPICE_INITIALIZED:
|
||||||
@ -310,7 +317,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'SPICE_INITIALIZED',
|
{ 'event': 'SPICE_INITIALIZED',
|
||||||
'data': { 'server': 'SpiceServerInfo',
|
'data': { 'server': 'SpiceServerInfo',
|
||||||
'client': 'SpiceChannel' } }
|
'client': 'SpiceChannel' },
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SPICE_DISCONNECTED:
|
# @SPICE_DISCONNECTED:
|
||||||
@ -335,7 +343,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'SPICE_DISCONNECTED',
|
{ 'event': 'SPICE_DISCONNECTED',
|
||||||
'data': { 'server': 'SpiceBasicInfo',
|
'data': { 'server': 'SpiceBasicInfo',
|
||||||
'client': 'SpiceBasicInfo' } }
|
'client': 'SpiceBasicInfo' },
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SPICE_MIGRATE_COMPLETED:
|
# @SPICE_MIGRATE_COMPLETED:
|
||||||
@ -350,7 +359,8 @@
|
|||||||
# "event": "SPICE_MIGRATE_COMPLETED" }
|
# "event": "SPICE_MIGRATE_COMPLETED" }
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
{ 'event': 'SPICE_MIGRATE_COMPLETED' }
|
{ 'event': 'SPICE_MIGRATE_COMPLETED',
|
||||||
|
'if': 'defined(CONFIG_SPICE)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# == VNC
|
# == VNC
|
||||||
@ -377,7 +387,8 @@
|
|||||||
'data': { 'host': 'str',
|
'data': { 'host': 'str',
|
||||||
'service': 'str',
|
'service': 'str',
|
||||||
'family': 'NetworkAddressFamily',
|
'family': 'NetworkAddressFamily',
|
||||||
'websocket': 'bool' } }
|
'websocket': 'bool' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncServerInfo:
|
# @VncServerInfo:
|
||||||
@ -391,7 +402,8 @@
|
|||||||
##
|
##
|
||||||
{ 'struct': 'VncServerInfo',
|
{ 'struct': 'VncServerInfo',
|
||||||
'base': 'VncBasicInfo',
|
'base': 'VncBasicInfo',
|
||||||
'data': { '*auth': 'str' } }
|
'data': { '*auth': 'str' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncClientInfo:
|
# @VncClientInfo:
|
||||||
@ -408,7 +420,8 @@
|
|||||||
##
|
##
|
||||||
{ 'struct': 'VncClientInfo',
|
{ 'struct': 'VncClientInfo',
|
||||||
'base': 'VncBasicInfo',
|
'base': 'VncBasicInfo',
|
||||||
'data': { '*x509_dname': 'str', '*sasl_username': 'str' } }
|
'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncInfo:
|
# @VncInfo:
|
||||||
@ -449,7 +462,8 @@
|
|||||||
{ 'struct': 'VncInfo',
|
{ 'struct': 'VncInfo',
|
||||||
'data': {'enabled': 'bool', '*host': 'str',
|
'data': {'enabled': 'bool', '*host': 'str',
|
||||||
'*family': 'NetworkAddressFamily',
|
'*family': 'NetworkAddressFamily',
|
||||||
'*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']} }
|
'*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']},
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncPrimaryAuth:
|
# @VncPrimaryAuth:
|
||||||
@ -460,7 +474,8 @@
|
|||||||
##
|
##
|
||||||
{ 'enum': 'VncPrimaryAuth',
|
{ 'enum': 'VncPrimaryAuth',
|
||||||
'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
|
'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
|
||||||
'tls', 'vencrypt', 'sasl' ] }
|
'tls', 'vencrypt', 'sasl' ],
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncVencryptSubAuth:
|
# @VncVencryptSubAuth:
|
||||||
@ -474,8 +489,8 @@
|
|||||||
'tls-none', 'x509-none',
|
'tls-none', 'x509-none',
|
||||||
'tls-vnc', 'x509-vnc',
|
'tls-vnc', 'x509-vnc',
|
||||||
'tls-plain', 'x509-plain',
|
'tls-plain', 'x509-plain',
|
||||||
'tls-sasl', 'x509-sasl' ] }
|
'tls-sasl', 'x509-sasl' ],
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncServerInfo2:
|
# @VncServerInfo2:
|
||||||
@ -492,8 +507,8 @@
|
|||||||
{ 'struct': 'VncServerInfo2',
|
{ 'struct': 'VncServerInfo2',
|
||||||
'base': 'VncBasicInfo',
|
'base': 'VncBasicInfo',
|
||||||
'data': { 'auth' : 'VncPrimaryAuth',
|
'data': { 'auth' : 'VncPrimaryAuth',
|
||||||
'*vencrypt' : 'VncVencryptSubAuth' } }
|
'*vencrypt' : 'VncVencryptSubAuth' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VncInfo2:
|
# @VncInfo2:
|
||||||
@ -525,7 +540,8 @@
|
|||||||
'clients' : ['VncClientInfo'],
|
'clients' : ['VncClientInfo'],
|
||||||
'auth' : 'VncPrimaryAuth',
|
'auth' : 'VncPrimaryAuth',
|
||||||
'*vencrypt' : 'VncVencryptSubAuth',
|
'*vencrypt' : 'VncVencryptSubAuth',
|
||||||
'*display' : 'str' } }
|
'*display' : 'str' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @query-vnc:
|
# @query-vnc:
|
||||||
@ -556,8 +572,8 @@
|
|||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
##
|
##
|
||||||
{ 'command': 'query-vnc', 'returns': 'VncInfo' }
|
{ 'command': 'query-vnc', 'returns': 'VncInfo',
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
##
|
##
|
||||||
# @query-vnc-servers:
|
# @query-vnc-servers:
|
||||||
#
|
#
|
||||||
@ -567,7 +583,8 @@
|
|||||||
#
|
#
|
||||||
# Since: 2.3
|
# Since: 2.3
|
||||||
##
|
##
|
||||||
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'] }
|
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @change-vnc-password:
|
# @change-vnc-password:
|
||||||
@ -581,7 +598,8 @@
|
|||||||
# Notes: An empty password in this command will set the password to the empty
|
# Notes: An empty password in this command will set the password to the empty
|
||||||
# string. Existing clients are unaffected by executing this command.
|
# string. Existing clients are unaffected by executing this command.
|
||||||
##
|
##
|
||||||
{ 'command': 'change-vnc-password', 'data': {'password': 'str'} }
|
{ 'command': 'change-vnc-password', 'data': {'password': 'str'},
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VNC_CONNECTED:
|
# @VNC_CONNECTED:
|
||||||
@ -610,7 +628,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'VNC_CONNECTED',
|
{ 'event': 'VNC_CONNECTED',
|
||||||
'data': { 'server': 'VncServerInfo',
|
'data': { 'server': 'VncServerInfo',
|
||||||
'client': 'VncBasicInfo' } }
|
'client': 'VncBasicInfo' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VNC_INITIALIZED:
|
# @VNC_INITIALIZED:
|
||||||
@ -637,7 +656,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'VNC_INITIALIZED',
|
{ 'event': 'VNC_INITIALIZED',
|
||||||
'data': { 'server': 'VncServerInfo',
|
'data': { 'server': 'VncServerInfo',
|
||||||
'client': 'VncClientInfo' } }
|
'client': 'VncClientInfo' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @VNC_DISCONNECTED:
|
# @VNC_DISCONNECTED:
|
||||||
@ -663,7 +683,8 @@
|
|||||||
##
|
##
|
||||||
{ 'event': 'VNC_DISCONNECTED',
|
{ 'event': 'VNC_DISCONNECTED',
|
||||||
'data': { 'server': 'VncServerInfo',
|
'data': { 'server': 'VncServerInfo',
|
||||||
'client': 'VncClientInfo' } }
|
'client': 'VncClientInfo' },
|
||||||
|
'if': 'defined(CONFIG_VNC)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# = Input
|
# = Input
|
||||||
|
46
qmp.c
46
qmp.c
@ -129,38 +129,6 @@ void qmp_cpu_add(int64_t id, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_VNC
|
|
||||||
/* If VNC support is enabled, the "true" query-vnc command is
|
|
||||||
defined in the VNC subsystem */
|
|
||||||
VncInfo *qmp_query_vnc(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
|
|
||||||
VncInfo2List *qmp_query_vnc_servers(Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_SPICE
|
|
||||||
/*
|
|
||||||
* qmp_unregister_commands_hack() ensures that QMP command query-spice
|
|
||||||
* exists only #ifdef CONFIG_SPICE. Necessary for an accurate
|
|
||||||
* query-commands result. However, the QAPI schema is blissfully
|
|
||||||
* unaware of that, and the QAPI code generator happily generates a
|
|
||||||
* dead qmp_marshal_query_spice() that calls qmp_query_spice().
|
|
||||||
* Provide it one, or else linking fails. FIXME Educate the QAPI
|
|
||||||
* schema on CONFIG_SPICE.
|
|
||||||
*/
|
|
||||||
SpiceInfo *qmp_query_spice(Error **errp)
|
|
||||||
{
|
|
||||||
abort();
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void qmp_exit_preconfig(Error **errp)
|
void qmp_exit_preconfig(Error **errp)
|
||||||
{
|
{
|
||||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
||||||
@ -412,23 +380,17 @@ static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
|
|||||||
qmp_change_vnc_listen(target, errp);
|
qmp_change_vnc_listen(target, errp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void qmp_change_vnc_password(const char *password, Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
|
|
||||||
}
|
|
||||||
static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_VNC */
|
#endif /* !CONFIG_VNC */
|
||||||
|
|
||||||
void qmp_change(const char *device, const char *target,
|
void qmp_change(const char *device, const char *target,
|
||||||
bool has_arg, const char *arg, Error **errp)
|
bool has_arg, const char *arg, Error **errp)
|
||||||
{
|
{
|
||||||
if (strcmp(device, "vnc") == 0) {
|
if (strcmp(device, "vnc") == 0) {
|
||||||
|
#ifdef CONFIG_VNC
|
||||||
qmp_change_vnc(target, has_arg, arg, errp);
|
qmp_change_vnc(target, has_arg, arg, errp);
|
||||||
|
#else
|
||||||
|
error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
qmp_blockdev_change_medium(true, device, false, NULL, target,
|
qmp_blockdev_change_medium(true, device, false, NULL, target,
|
||||||
has_arg, arg, false, 0, errp);
|
has_arg, arg, false, 0, errp);
|
||||||
|
@ -239,7 +239,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
|
|||||||
QAPISchemaModularCVisitor.__init__(
|
QAPISchemaModularCVisitor.__init__(
|
||||||
self, prefix, 'qapi-commands',
|
self, prefix, 'qapi-commands',
|
||||||
' * Schema-defined QAPI/QMP commands', __doc__)
|
' * Schema-defined QAPI/QMP commands', __doc__)
|
||||||
self._regy = ''
|
self._regy = QAPIGenCCode()
|
||||||
self._visited_ret_types = {}
|
self._visited_ret_types = {}
|
||||||
|
|
||||||
def _begin_module(self, name):
|
def _begin_module(self, name):
|
||||||
@ -275,20 +275,28 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
|
|||||||
void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
|
void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
|
||||||
''',
|
''',
|
||||||
c_prefix=c_name(self._prefix, protect=False)))
|
c_prefix=c_name(self._prefix, protect=False)))
|
||||||
genc.add(gen_registry(self._regy, self._prefix))
|
genc.add(gen_registry(self._regy.get_content(), self._prefix))
|
||||||
|
|
||||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig):
|
success_response, boxed, allow_oob, allow_preconfig):
|
||||||
if not gen:
|
if not gen:
|
||||||
return
|
return
|
||||||
self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
|
# FIXME: If T is a user-defined type, the user is responsible
|
||||||
|
# for making this work, i.e. to make T's condition the
|
||||||
|
# conjunction of the T-returning commands' conditions. If T
|
||||||
|
# is a built-in type, this isn't possible: the
|
||||||
|
# qmp_marshal_output_T() will be generated unconditionally.
|
||||||
if ret_type and ret_type not in self._visited_ret_types[self._genc]:
|
if ret_type and ret_type not in self._visited_ret_types[self._genc]:
|
||||||
self._visited_ret_types[self._genc].add(ret_type)
|
self._visited_ret_types[self._genc].add(ret_type)
|
||||||
self._genc.add(gen_marshal_output(ret_type))
|
with ifcontext(ret_type.ifcond,
|
||||||
self._genh.add(gen_marshal_decl(name))
|
self._genh, self._genc, self._regy):
|
||||||
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
|
self._genc.add(gen_marshal_output(ret_type))
|
||||||
self._regy += gen_register_command(name, success_response, allow_oob,
|
with ifcontext(ifcond, self._genh, self._genc, self._regy):
|
||||||
allow_preconfig)
|
self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
|
||||||
|
self._genh.add(gen_marshal_decl(name))
|
||||||
|
self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
|
||||||
|
self._regy.add(gen_register_command(name, success_response,
|
||||||
|
allow_oob, allow_preconfig))
|
||||||
|
|
||||||
|
|
||||||
def gen_commands(schema, output_dir, prefix):
|
def gen_commands(schema, output_dir, prefix):
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# See the COPYING file in the top-level directory.
|
# See the COPYING file in the top-level directory.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
from contextlib import contextmanager
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -638,6 +639,27 @@ def add_name(name, info, meta, implicit=False):
|
|||||||
all_names[name] = meta
|
all_names[name] = meta
|
||||||
|
|
||||||
|
|
||||||
|
def check_if(expr, info):
|
||||||
|
|
||||||
|
def check_if_str(ifcond, info):
|
||||||
|
if not isinstance(ifcond, str):
|
||||||
|
raise QAPISemError(
|
||||||
|
info, "'if' condition must be a string or a list of strings")
|
||||||
|
if ifcond == '':
|
||||||
|
raise QAPISemError(info, "'if' condition '' makes no sense")
|
||||||
|
|
||||||
|
ifcond = expr.get('if')
|
||||||
|
if ifcond is None:
|
||||||
|
return
|
||||||
|
if isinstance(ifcond, list):
|
||||||
|
if ifcond == []:
|
||||||
|
raise QAPISemError(info, "'if' condition [] is useless")
|
||||||
|
for elt in ifcond:
|
||||||
|
check_if_str(elt, info)
|
||||||
|
else:
|
||||||
|
check_if_str(ifcond, info)
|
||||||
|
|
||||||
|
|
||||||
def check_type(info, source, value, allow_array=False,
|
def check_type(info, source, value, allow_array=False,
|
||||||
allow_dict=False, allow_optional=False,
|
allow_dict=False, allow_optional=False,
|
||||||
allow_metas=[]):
|
allow_metas=[]):
|
||||||
@ -871,6 +893,8 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
|||||||
raise QAPISemError(info,
|
raise QAPISemError(info,
|
||||||
"'%s' of %s '%s' should only use true value"
|
"'%s' of %s '%s' should only use true value"
|
||||||
% (key, meta, name))
|
% (key, meta, name))
|
||||||
|
if key == 'if':
|
||||||
|
check_if(expr, info)
|
||||||
for key in required:
|
for key in required:
|
||||||
if key not in expr:
|
if key not in expr:
|
||||||
raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
|
raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
|
||||||
@ -899,28 +923,28 @@ def check_exprs(exprs):
|
|||||||
|
|
||||||
if 'enum' in expr:
|
if 'enum' in expr:
|
||||||
meta = 'enum'
|
meta = 'enum'
|
||||||
check_keys(expr_elem, 'enum', ['data'], ['prefix'])
|
check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix'])
|
||||||
enum_types[expr[meta]] = expr
|
enum_types[expr[meta]] = expr
|
||||||
elif 'union' in expr:
|
elif 'union' in expr:
|
||||||
meta = 'union'
|
meta = 'union'
|
||||||
check_keys(expr_elem, 'union', ['data'],
|
check_keys(expr_elem, 'union', ['data'],
|
||||||
['base', 'discriminator'])
|
['base', 'discriminator', 'if'])
|
||||||
union_types[expr[meta]] = expr
|
union_types[expr[meta]] = expr
|
||||||
elif 'alternate' in expr:
|
elif 'alternate' in expr:
|
||||||
meta = 'alternate'
|
meta = 'alternate'
|
||||||
check_keys(expr_elem, 'alternate', ['data'])
|
check_keys(expr_elem, 'alternate', ['data'], ['if'])
|
||||||
elif 'struct' in expr:
|
elif 'struct' in expr:
|
||||||
meta = 'struct'
|
meta = 'struct'
|
||||||
check_keys(expr_elem, 'struct', ['data'], ['base'])
|
check_keys(expr_elem, 'struct', ['data'], ['base', 'if'])
|
||||||
struct_types[expr[meta]] = expr
|
struct_types[expr[meta]] = expr
|
||||||
elif 'command' in expr:
|
elif 'command' in expr:
|
||||||
meta = 'command'
|
meta = 'command'
|
||||||
check_keys(expr_elem, 'command', [],
|
check_keys(expr_elem, 'command', [],
|
||||||
['data', 'returns', 'gen', 'success-response',
|
['data', 'returns', 'gen', 'success-response',
|
||||||
'boxed', 'allow-oob', 'allow-preconfig'])
|
'boxed', 'allow-oob', 'allow-preconfig', 'if'])
|
||||||
elif 'event' in expr:
|
elif 'event' in expr:
|
||||||
meta = 'event'
|
meta = 'event'
|
||||||
check_keys(expr_elem, 'event', [], ['data', 'boxed'])
|
check_keys(expr_elem, 'event', [], ['data', 'boxed', 'if'])
|
||||||
else:
|
else:
|
||||||
raise QAPISemError(expr_elem['info'],
|
raise QAPISemError(expr_elem['info'],
|
||||||
"Expression is missing metatype")
|
"Expression is missing metatype")
|
||||||
@ -978,8 +1002,16 @@ def check_exprs(exprs):
|
|||||||
# Schema compiler frontend
|
# Schema compiler frontend
|
||||||
#
|
#
|
||||||
|
|
||||||
|
def listify_cond(ifcond):
|
||||||
|
if not ifcond:
|
||||||
|
return []
|
||||||
|
if not isinstance(ifcond, list):
|
||||||
|
return [ifcond]
|
||||||
|
return ifcond
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaEntity(object):
|
class QAPISchemaEntity(object):
|
||||||
def __init__(self, name, info, doc):
|
def __init__(self, name, info, doc, ifcond=None):
|
||||||
assert name is None or isinstance(name, str)
|
assert name is None or isinstance(name, str)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.module = None
|
self.module = None
|
||||||
@ -990,12 +1022,19 @@ class QAPISchemaEntity(object):
|
|||||||
# such place).
|
# such place).
|
||||||
self.info = info
|
self.info = info
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
|
self._ifcond = ifcond # self.ifcond is set only after .check()
|
||||||
|
|
||||||
def c_name(self):
|
def c_name(self):
|
||||||
return c_name(self.name)
|
return c_name(self.name)
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
pass
|
if isinstance(self._ifcond, QAPISchemaType):
|
||||||
|
# inherit the condition from a type
|
||||||
|
typ = self._ifcond
|
||||||
|
typ.check(schema)
|
||||||
|
self.ifcond = typ.ifcond
|
||||||
|
else:
|
||||||
|
self.ifcond = listify_cond(self._ifcond)
|
||||||
|
|
||||||
def is_implicit(self):
|
def is_implicit(self):
|
||||||
return not self.info
|
return not self.info
|
||||||
@ -1024,26 +1063,26 @@ class QAPISchemaVisitor(object):
|
|||||||
def visit_builtin_type(self, name, info, json_type):
|
def visit_builtin_type(self, name, info, json_type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_array_type(self, name, info, element_type):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_object_type_flat(self, name, info, members, variants):
|
def visit_object_type_flat(self, name, info, ifcond, members, variants):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig):
|
success_response, boxed, allow_oob, allow_preconfig):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_event(self, name, info, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -1122,8 +1161,8 @@ class QAPISchemaBuiltinType(QAPISchemaType):
|
|||||||
|
|
||||||
|
|
||||||
class QAPISchemaEnumType(QAPISchemaType):
|
class QAPISchemaEnumType(QAPISchemaType):
|
||||||
def __init__(self, name, info, doc, values, prefix):
|
def __init__(self, name, info, doc, ifcond, values, prefix):
|
||||||
QAPISchemaType.__init__(self, name, info, doc)
|
QAPISchemaType.__init__(self, name, info, doc, ifcond)
|
||||||
for v in values:
|
for v in values:
|
||||||
assert isinstance(v, QAPISchemaMember)
|
assert isinstance(v, QAPISchemaMember)
|
||||||
v.set_owner(name)
|
v.set_owner(name)
|
||||||
@ -1132,6 +1171,7 @@ class QAPISchemaEnumType(QAPISchemaType):
|
|||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaType.check(self, schema)
|
||||||
seen = {}
|
seen = {}
|
||||||
for v in self.values:
|
for v in self.values:
|
||||||
v.check_clash(self.info, seen)
|
v.check_clash(self.info, seen)
|
||||||
@ -1152,20 +1192,23 @@ class QAPISchemaEnumType(QAPISchemaType):
|
|||||||
return 'string'
|
return 'string'
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_enum_type(self.name, self.info,
|
visitor.visit_enum_type(self.name, self.info, self.ifcond,
|
||||||
self.member_names(), self.prefix)
|
self.member_names(), self.prefix)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaArrayType(QAPISchemaType):
|
class QAPISchemaArrayType(QAPISchemaType):
|
||||||
def __init__(self, name, info, element_type):
|
def __init__(self, name, info, element_type):
|
||||||
QAPISchemaType.__init__(self, name, info, None)
|
QAPISchemaType.__init__(self, name, info, None, None)
|
||||||
assert isinstance(element_type, str)
|
assert isinstance(element_type, str)
|
||||||
self._element_type_name = element_type
|
self._element_type_name = element_type
|
||||||
self.element_type = None
|
self.element_type = None
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaType.check(self, schema)
|
||||||
self.element_type = schema.lookup_type(self._element_type_name)
|
self.element_type = schema.lookup_type(self._element_type_name)
|
||||||
assert self.element_type
|
assert self.element_type
|
||||||
|
self.element_type.check(schema)
|
||||||
|
self.ifcond = self.element_type.ifcond
|
||||||
|
|
||||||
def is_implicit(self):
|
def is_implicit(self):
|
||||||
return True
|
return True
|
||||||
@ -1183,15 +1226,17 @@ class QAPISchemaArrayType(QAPISchemaType):
|
|||||||
return 'array of ' + elt_doc_type
|
return 'array of ' + elt_doc_type
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_array_type(self.name, self.info, self.element_type)
|
visitor.visit_array_type(self.name, self.info, self.ifcond,
|
||||||
|
self.element_type)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaObjectType(QAPISchemaType):
|
class QAPISchemaObjectType(QAPISchemaType):
|
||||||
def __init__(self, name, info, doc, base, local_members, variants):
|
def __init__(self, name, info, doc, ifcond,
|
||||||
|
base, local_members, variants):
|
||||||
# struct has local_members, optional base, and no variants
|
# struct has local_members, optional base, and no variants
|
||||||
# flat union has base, variants, and no local_members
|
# flat union has base, variants, and no local_members
|
||||||
# simple union has local_members, variants, and no base
|
# simple union has local_members, variants, and no base
|
||||||
QAPISchemaType.__init__(self, name, info, doc)
|
QAPISchemaType.__init__(self, name, info, doc, ifcond)
|
||||||
assert base is None or isinstance(base, str)
|
assert base is None or isinstance(base, str)
|
||||||
for m in local_members:
|
for m in local_members:
|
||||||
assert isinstance(m, QAPISchemaObjectTypeMember)
|
assert isinstance(m, QAPISchemaObjectTypeMember)
|
||||||
@ -1206,6 +1251,7 @@ class QAPISchemaObjectType(QAPISchemaType):
|
|||||||
self.members = None
|
self.members = None
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaType.check(self, schema)
|
||||||
if self.members is False: # check for cycles
|
if self.members is False: # check for cycles
|
||||||
raise QAPISemError(self.info,
|
raise QAPISemError(self.info,
|
||||||
"Object %s contains itself" % self.name)
|
"Object %s contains itself" % self.name)
|
||||||
@ -1263,9 +1309,9 @@ class QAPISchemaObjectType(QAPISchemaType):
|
|||||||
return 'object'
|
return 'object'
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_object_type(self.name, self.info,
|
visitor.visit_object_type(self.name, self.info, self.ifcond,
|
||||||
self.base, self.local_members, self.variants)
|
self.base, self.local_members, self.variants)
|
||||||
visitor.visit_object_type_flat(self.name, self.info,
|
visitor.visit_object_type_flat(self.name, self.info, self.ifcond,
|
||||||
self.members, self.variants)
|
self.members, self.variants)
|
||||||
|
|
||||||
|
|
||||||
@ -1387,8 +1433,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
|||||||
|
|
||||||
|
|
||||||
class QAPISchemaAlternateType(QAPISchemaType):
|
class QAPISchemaAlternateType(QAPISchemaType):
|
||||||
def __init__(self, name, info, doc, variants):
|
def __init__(self, name, info, doc, ifcond, variants):
|
||||||
QAPISchemaType.__init__(self, name, info, doc)
|
QAPISchemaType.__init__(self, name, info, doc, ifcond)
|
||||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||||
assert variants.tag_member
|
assert variants.tag_member
|
||||||
variants.set_owner(name)
|
variants.set_owner(name)
|
||||||
@ -1396,6 +1442,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
|||||||
self.variants = variants
|
self.variants = variants
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaType.check(self, schema)
|
||||||
self.variants.tag_member.check(schema)
|
self.variants.tag_member.check(schema)
|
||||||
# Not calling self.variants.check_clash(), because there's nothing
|
# Not calling self.variants.check_clash(), because there's nothing
|
||||||
# to clash with
|
# to clash with
|
||||||
@ -1417,16 +1464,17 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
|||||||
return 'value'
|
return 'value'
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_alternate_type(self.name, self.info, self.variants)
|
visitor.visit_alternate_type(self.name, self.info, self.ifcond,
|
||||||
|
self.variants)
|
||||||
|
|
||||||
def is_empty(self):
|
def is_empty(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaCommand(QAPISchemaEntity):
|
class QAPISchemaCommand(QAPISchemaEntity):
|
||||||
def __init__(self, name, info, doc, arg_type, ret_type,
|
def __init__(self, name, info, doc, ifcond, arg_type, ret_type,
|
||||||
gen, success_response, boxed, allow_oob, allow_preconfig):
|
gen, success_response, boxed, allow_oob, allow_preconfig):
|
||||||
QAPISchemaEntity.__init__(self, name, info, doc)
|
QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
|
||||||
assert not arg_type or isinstance(arg_type, str)
|
assert not arg_type or isinstance(arg_type, str)
|
||||||
assert not ret_type or isinstance(ret_type, str)
|
assert not ret_type or isinstance(ret_type, str)
|
||||||
self._arg_type_name = arg_type
|
self._arg_type_name = arg_type
|
||||||
@ -1440,6 +1488,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
|||||||
self.allow_preconfig = allow_preconfig
|
self.allow_preconfig = allow_preconfig
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaEntity.check(self, schema)
|
||||||
if self._arg_type_name:
|
if self._arg_type_name:
|
||||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||||
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
||||||
@ -1459,7 +1508,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
|||||||
assert isinstance(self.ret_type, QAPISchemaType)
|
assert isinstance(self.ret_type, QAPISchemaType)
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_command(self.name, self.info,
|
visitor.visit_command(self.name, self.info, self.ifcond,
|
||||||
self.arg_type, self.ret_type,
|
self.arg_type, self.ret_type,
|
||||||
self.gen, self.success_response,
|
self.gen, self.success_response,
|
||||||
self.boxed, self.allow_oob,
|
self.boxed, self.allow_oob,
|
||||||
@ -1467,14 +1516,15 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
|||||||
|
|
||||||
|
|
||||||
class QAPISchemaEvent(QAPISchemaEntity):
|
class QAPISchemaEvent(QAPISchemaEntity):
|
||||||
def __init__(self, name, info, doc, arg_type, boxed):
|
def __init__(self, name, info, doc, ifcond, arg_type, boxed):
|
||||||
QAPISchemaEntity.__init__(self, name, info, doc)
|
QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
|
||||||
assert not arg_type or isinstance(arg_type, str)
|
assert not arg_type or isinstance(arg_type, str)
|
||||||
self._arg_type_name = arg_type
|
self._arg_type_name = arg_type
|
||||||
self.arg_type = None
|
self.arg_type = None
|
||||||
self.boxed = boxed
|
self.boxed = boxed
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
|
QAPISchemaEntity.check(self, schema)
|
||||||
if self._arg_type_name:
|
if self._arg_type_name:
|
||||||
self.arg_type = schema.lookup_type(self._arg_type_name)
|
self.arg_type = schema.lookup_type(self._arg_type_name)
|
||||||
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
assert (isinstance(self.arg_type, QAPISchemaObjectType) or
|
||||||
@ -1491,7 +1541,8 @@ class QAPISchemaEvent(QAPISchemaEntity):
|
|||||||
raise QAPISemError(self.info, "Use of 'boxed' requires 'data'")
|
raise QAPISemError(self.info, "Use of 'boxed' requires 'data'")
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
visitor.visit_event(self.name, self.info, self.arg_type, self.boxed)
|
visitor.visit_event(self.name, self.info, self.ifcond,
|
||||||
|
self.arg_type, self.boxed)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchema(object):
|
class QAPISchema(object):
|
||||||
@ -1567,22 +1618,22 @@ class QAPISchema(object):
|
|||||||
('null', 'null', 'QNull' + pointer_suffix)]:
|
('null', 'null', 'QNull' + pointer_suffix)]:
|
||||||
self._def_builtin_type(*t)
|
self._def_builtin_type(*t)
|
||||||
self.the_empty_object_type = QAPISchemaObjectType(
|
self.the_empty_object_type = QAPISchemaObjectType(
|
||||||
'q_empty', None, None, None, [], None)
|
'q_empty', None, None, None, None, [], None)
|
||||||
self._def_entity(self.the_empty_object_type)
|
self._def_entity(self.the_empty_object_type)
|
||||||
qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
|
qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
|
||||||
'qstring', 'qdict', 'qlist',
|
'qstring', 'qdict', 'qlist',
|
||||||
'qbool'])
|
'qbool'])
|
||||||
self._def_entity(QAPISchemaEnumType('QType', None, None,
|
self._def_entity(QAPISchemaEnumType('QType', None, None, None,
|
||||||
qtype_values, 'QTYPE'))
|
qtype_values, 'QTYPE'))
|
||||||
|
|
||||||
def _make_enum_members(self, values):
|
def _make_enum_members(self, values):
|
||||||
return [QAPISchemaMember(v) for v in values]
|
return [QAPISchemaMember(v) for v in values]
|
||||||
|
|
||||||
def _make_implicit_enum_type(self, name, info, values):
|
def _make_implicit_enum_type(self, name, info, ifcond, values):
|
||||||
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
||||||
name = name + 'Kind' # Use namespace reserved by add_name()
|
name = name + 'Kind' # Use namespace reserved by add_name()
|
||||||
self._def_entity(QAPISchemaEnumType(
|
self._def_entity(QAPISchemaEnumType(
|
||||||
name, info, None, self._make_enum_members(values), None))
|
name, info, None, ifcond, self._make_enum_members(values), None))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def _make_array_type(self, element_type, info):
|
def _make_array_type(self, element_type, info):
|
||||||
@ -1591,22 +1642,37 @@ class QAPISchema(object):
|
|||||||
self._def_entity(QAPISchemaArrayType(name, info, element_type))
|
self._def_entity(QAPISchemaArrayType(name, info, element_type))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def _make_implicit_object_type(self, name, info, doc, role, members):
|
def _make_implicit_object_type(self, name, info, doc, ifcond,
|
||||||
|
role, members):
|
||||||
if not members:
|
if not members:
|
||||||
return None
|
return None
|
||||||
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
||||||
name = 'q_obj_%s-%s' % (name, role)
|
name = 'q_obj_%s-%s' % (name, role)
|
||||||
if not self.lookup_entity(name, QAPISchemaObjectType):
|
typ = self.lookup_entity(name, QAPISchemaObjectType)
|
||||||
self._def_entity(QAPISchemaObjectType(name, info, doc, None,
|
if typ:
|
||||||
members, None))
|
# The implicit object type has multiple users. This can
|
||||||
|
# happen only for simple unions' implicit wrapper types.
|
||||||
|
# Its ifcond should be the disjunction of its user's
|
||||||
|
# ifconds. Not implemented. Instead, we always pass the
|
||||||
|
# wrapped type's ifcond, which is trivially the same for all
|
||||||
|
# users. It's also necessary for the wrapper to compile.
|
||||||
|
# But it's not tight: the disjunction need not imply it. We
|
||||||
|
# may end up compiling useless wrapper types.
|
||||||
|
# TODO kill simple unions or implement the disjunction
|
||||||
|
assert ifcond == typ._ifcond # pylint: disable=protected-access
|
||||||
|
else:
|
||||||
|
self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
|
||||||
|
None, members, None))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def _def_enum_type(self, expr, info, doc):
|
def _def_enum_type(self, expr, info, doc):
|
||||||
name = expr['enum']
|
name = expr['enum']
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
prefix = expr.get('prefix')
|
prefix = expr.get('prefix')
|
||||||
|
ifcond = expr.get('if')
|
||||||
self._def_entity(QAPISchemaEnumType(
|
self._def_entity(QAPISchemaEnumType(
|
||||||
name, info, doc, self._make_enum_members(data), prefix))
|
name, info, doc, ifcond,
|
||||||
|
self._make_enum_members(data), prefix))
|
||||||
|
|
||||||
def _make_member(self, name, typ, info):
|
def _make_member(self, name, typ, info):
|
||||||
optional = False
|
optional = False
|
||||||
@ -1626,7 +1692,8 @@ class QAPISchema(object):
|
|||||||
name = expr['struct']
|
name = expr['struct']
|
||||||
base = expr.get('base')
|
base = expr.get('base')
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
self._def_entity(QAPISchemaObjectType(name, info, doc, base,
|
ifcond = expr.get('if')
|
||||||
|
self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond, base,
|
||||||
self._make_members(data, info),
|
self._make_members(data, info),
|
||||||
None))
|
None))
|
||||||
|
|
||||||
@ -1638,18 +1705,21 @@ class QAPISchema(object):
|
|||||||
assert len(typ) == 1
|
assert len(typ) == 1
|
||||||
typ = self._make_array_type(typ[0], info)
|
typ = self._make_array_type(typ[0], info)
|
||||||
typ = self._make_implicit_object_type(
|
typ = self._make_implicit_object_type(
|
||||||
typ, info, None, 'wrapper', [self._make_member('data', typ, info)])
|
typ, info, None, self.lookup_type(typ),
|
||||||
|
'wrapper', [self._make_member('data', typ, info)])
|
||||||
return QAPISchemaObjectTypeVariant(case, typ)
|
return QAPISchemaObjectTypeVariant(case, typ)
|
||||||
|
|
||||||
def _def_union_type(self, expr, info, doc):
|
def _def_union_type(self, expr, info, doc):
|
||||||
name = expr['union']
|
name = expr['union']
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
base = expr.get('base')
|
base = expr.get('base')
|
||||||
|
ifcond = expr.get('if')
|
||||||
tag_name = expr.get('discriminator')
|
tag_name = expr.get('discriminator')
|
||||||
tag_member = None
|
tag_member = None
|
||||||
if isinstance(base, dict):
|
if isinstance(base, dict):
|
||||||
base = (self._make_implicit_object_type(
|
base = self._make_implicit_object_type(
|
||||||
name, info, doc, 'base', self._make_members(base, info)))
|
name, info, doc, ifcond,
|
||||||
|
'base', self._make_members(base, info))
|
||||||
if tag_name:
|
if tag_name:
|
||||||
variants = [self._make_variant(key, value)
|
variants = [self._make_variant(key, value)
|
||||||
for (key, value) in data.items()]
|
for (key, value) in data.items()]
|
||||||
@ -1657,12 +1727,12 @@ class QAPISchema(object):
|
|||||||
else:
|
else:
|
||||||
variants = [self._make_simple_variant(key, value, info)
|
variants = [self._make_simple_variant(key, value, info)
|
||||||
for (key, value) in data.items()]
|
for (key, value) in data.items()]
|
||||||
typ = self._make_implicit_enum_type(name, info,
|
typ = self._make_implicit_enum_type(name, info, ifcond,
|
||||||
[v.name for v in variants])
|
[v.name for v in variants])
|
||||||
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
|
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
|
||||||
members = [tag_member]
|
members = [tag_member]
|
||||||
self._def_entity(
|
self._def_entity(
|
||||||
QAPISchemaObjectType(name, info, doc, base, members,
|
QAPISchemaObjectType(name, info, doc, ifcond, base, members,
|
||||||
QAPISchemaObjectTypeVariants(tag_name,
|
QAPISchemaObjectTypeVariants(tag_name,
|
||||||
tag_member,
|
tag_member,
|
||||||
variants)))
|
variants)))
|
||||||
@ -1670,11 +1740,12 @@ class QAPISchema(object):
|
|||||||
def _def_alternate_type(self, expr, info, doc):
|
def _def_alternate_type(self, expr, info, doc):
|
||||||
name = expr['alternate']
|
name = expr['alternate']
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
|
ifcond = expr.get('if')
|
||||||
variants = [self._make_variant(key, value)
|
variants = [self._make_variant(key, value)
|
||||||
for (key, value) in data.items()]
|
for (key, value) in data.items()]
|
||||||
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
|
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
|
||||||
self._def_entity(
|
self._def_entity(
|
||||||
QAPISchemaAlternateType(name, info, doc,
|
QAPISchemaAlternateType(name, info, doc, ifcond,
|
||||||
QAPISchemaObjectTypeVariants(None,
|
QAPISchemaObjectTypeVariants(None,
|
||||||
tag_member,
|
tag_member,
|
||||||
variants)))
|
variants)))
|
||||||
@ -1688,13 +1759,14 @@ class QAPISchema(object):
|
|||||||
boxed = expr.get('boxed', False)
|
boxed = expr.get('boxed', False)
|
||||||
allow_oob = expr.get('allow-oob', False)
|
allow_oob = expr.get('allow-oob', False)
|
||||||
allow_preconfig = expr.get('allow-preconfig', False)
|
allow_preconfig = expr.get('allow-preconfig', False)
|
||||||
|
ifcond = expr.get('if')
|
||||||
if isinstance(data, OrderedDict):
|
if isinstance(data, OrderedDict):
|
||||||
data = self._make_implicit_object_type(
|
data = self._make_implicit_object_type(
|
||||||
name, info, doc, 'arg', self._make_members(data, info))
|
name, info, doc, ifcond, 'arg', self._make_members(data, info))
|
||||||
if isinstance(rets, list):
|
if isinstance(rets, list):
|
||||||
assert len(rets) == 1
|
assert len(rets) == 1
|
||||||
rets = self._make_array_type(rets[0], info)
|
rets = self._make_array_type(rets[0], info)
|
||||||
self._def_entity(QAPISchemaCommand(name, info, doc, data, rets,
|
self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, rets,
|
||||||
gen, success_response,
|
gen, success_response,
|
||||||
boxed, allow_oob, allow_preconfig))
|
boxed, allow_oob, allow_preconfig))
|
||||||
|
|
||||||
@ -1702,10 +1774,11 @@ class QAPISchema(object):
|
|||||||
name = expr['event']
|
name = expr['event']
|
||||||
data = expr.get('data')
|
data = expr.get('data')
|
||||||
boxed = expr.get('boxed', False)
|
boxed = expr.get('boxed', False)
|
||||||
|
ifcond = expr.get('if')
|
||||||
if isinstance(data, OrderedDict):
|
if isinstance(data, OrderedDict):
|
||||||
data = self._make_implicit_object_type(
|
data = self._make_implicit_object_type(
|
||||||
name, info, doc, 'arg', self._make_members(data, info))
|
name, info, doc, ifcond, 'arg', self._make_members(data, info))
|
||||||
self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed))
|
self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, data, boxed))
|
||||||
|
|
||||||
def _def_exprs(self, exprs):
|
def _def_exprs(self, exprs):
|
||||||
for expr_elem in exprs:
|
for expr_elem in exprs:
|
||||||
@ -1869,8 +1942,8 @@ def cgen(code, **kwds):
|
|||||||
if indent_level:
|
if indent_level:
|
||||||
indent = genindent(indent_level)
|
indent = genindent(indent_level)
|
||||||
# re.subn() lacks flags support before Python 2.7, use re.compile()
|
# re.subn() lacks flags support before Python 2.7, use re.compile()
|
||||||
raw = re.subn(re.compile(r'^.', re.MULTILINE),
|
raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE),
|
||||||
indent + r'\g<0>', raw)
|
indent, raw)
|
||||||
raw = raw[0]
|
raw = raw[0]
|
||||||
return re.sub(re.escape(eatspace) + r' *', '', raw)
|
return re.sub(re.escape(eatspace) + r' *', '', raw)
|
||||||
|
|
||||||
@ -1902,6 +1975,40 @@ def guardend(name):
|
|||||||
name=guardname(name))
|
name=guardname(name))
|
||||||
|
|
||||||
|
|
||||||
|
def gen_if(ifcond):
|
||||||
|
ret = ''
|
||||||
|
for ifc in ifcond:
|
||||||
|
ret += mcgen('''
|
||||||
|
#if %(cond)s
|
||||||
|
''', cond=ifc)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def gen_endif(ifcond):
|
||||||
|
ret = ''
|
||||||
|
for ifc in reversed(ifcond):
|
||||||
|
ret += mcgen('''
|
||||||
|
#endif /* %(cond)s */
|
||||||
|
''', cond=ifc)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def _wrap_ifcond(ifcond, before, after):
|
||||||
|
if before == after:
|
||||||
|
return after # suppress empty #if ... #endif
|
||||||
|
|
||||||
|
assert after.startswith(before)
|
||||||
|
out = before
|
||||||
|
added = after[len(before):]
|
||||||
|
if added[0] == '\n':
|
||||||
|
out += '\n'
|
||||||
|
added = added[1:]
|
||||||
|
out += gen_if(ifcond)
|
||||||
|
out += added
|
||||||
|
out += gen_endif(ifcond)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def gen_enum_lookup(name, values, prefix=None):
|
def gen_enum_lookup(name, values, prefix=None):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
|
|
||||||
@ -1999,6 +2106,10 @@ class QAPIGen(object):
|
|||||||
def add(self, text):
|
def add(self, text):
|
||||||
self._body += text
|
self._body += text
|
||||||
|
|
||||||
|
def get_content(self, fname=None):
|
||||||
|
return (self._top(fname) + self._preamble + self._body
|
||||||
|
+ self._bottom(fname))
|
||||||
|
|
||||||
def _top(self, fname):
|
def _top(self, fname):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@ -2019,8 +2130,7 @@ class QAPIGen(object):
|
|||||||
f = open(fd, 'r+', encoding='utf-8')
|
f = open(fd, 'r+', encoding='utf-8')
|
||||||
else:
|
else:
|
||||||
f = os.fdopen(fd, 'r+')
|
f = os.fdopen(fd, 'r+')
|
||||||
text = (self._top(fname) + self._preamble + self._body
|
text = self.get_content(fname)
|
||||||
+ self._bottom(fname))
|
|
||||||
oldtext = f.read(len(text) + 1)
|
oldtext = f.read(len(text) + 1)
|
||||||
if text != oldtext:
|
if text != oldtext:
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
@ -2029,10 +2139,62 @@ class QAPIGen(object):
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
class QAPIGenC(QAPIGen):
|
@contextmanager
|
||||||
|
def ifcontext(ifcond, *args):
|
||||||
|
"""A 'with' statement context manager to wrap with start_if()/end_if()
|
||||||
|
|
||||||
|
*args: any number of QAPIGenCCode
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
|
modify self._genh and self._genc ...
|
||||||
|
|
||||||
|
Is equivalent to calling::
|
||||||
|
|
||||||
|
self._genh.start_if(ifcond)
|
||||||
|
self._genc.start_if(ifcond)
|
||||||
|
modify self._genh and self._genc ...
|
||||||
|
self._genh.end_if()
|
||||||
|
self._genc.end_if()
|
||||||
|
"""
|
||||||
|
for arg in args:
|
||||||
|
arg.start_if(ifcond)
|
||||||
|
yield
|
||||||
|
for arg in args:
|
||||||
|
arg.end_if()
|
||||||
|
|
||||||
|
|
||||||
|
class QAPIGenCCode(QAPIGen):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
QAPIGen.__init__(self)
|
||||||
|
self._start_if = None
|
||||||
|
|
||||||
|
def start_if(self, ifcond):
|
||||||
|
assert self._start_if is None
|
||||||
|
self._start_if = (ifcond, self._body, self._preamble)
|
||||||
|
|
||||||
|
def end_if(self):
|
||||||
|
assert self._start_if
|
||||||
|
self._wrap_ifcond()
|
||||||
|
self._start_if = None
|
||||||
|
|
||||||
|
def _wrap_ifcond(self):
|
||||||
|
self._body = _wrap_ifcond(self._start_if[0],
|
||||||
|
self._start_if[1], self._body)
|
||||||
|
self._preamble = _wrap_ifcond(self._start_if[0],
|
||||||
|
self._start_if[2], self._preamble)
|
||||||
|
|
||||||
|
def get_content(self, fname=None):
|
||||||
|
assert self._start_if is None
|
||||||
|
return QAPIGen.get_content(self, fname)
|
||||||
|
|
||||||
|
|
||||||
|
class QAPIGenC(QAPIGenCCode):
|
||||||
|
|
||||||
def __init__(self, blurb, pydoc):
|
def __init__(self, blurb, pydoc):
|
||||||
QAPIGen.__init__(self)
|
QAPIGenCCode.__init__(self)
|
||||||
self._blurb = blurb
|
self._blurb = blurb
|
||||||
self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
|
self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
|
||||||
re.MULTILINE))
|
re.MULTILINE))
|
||||||
|
32
scripts/qapi/doc.py
Normal file → Executable file
32
scripts/qapi/doc.py
Normal file → Executable file
@ -174,7 +174,7 @@ def texi_members(doc, what, base, variants, member_func):
|
|||||||
return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
|
return '\n@b{%s:}\n@table @asis\n%s@end table\n' % (what, items)
|
||||||
|
|
||||||
|
|
||||||
def texi_sections(doc):
|
def texi_sections(doc, ifcond):
|
||||||
"""Format additional sections following arguments"""
|
"""Format additional sections following arguments"""
|
||||||
body = ''
|
body = ''
|
||||||
for section in doc.sections:
|
for section in doc.sections:
|
||||||
@ -185,14 +185,16 @@ def texi_sections(doc):
|
|||||||
body += texi_example(section.text)
|
body += texi_example(section.text)
|
||||||
else:
|
else:
|
||||||
body += texi_format(section.text)
|
body += texi_format(section.text)
|
||||||
|
if ifcond:
|
||||||
|
body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
||||||
def texi_entity(doc, what, base=None, variants=None,
|
def texi_entity(doc, what, ifcond, base=None, variants=None,
|
||||||
member_func=texi_member):
|
member_func=texi_member):
|
||||||
return (texi_body(doc)
|
return (texi_body(doc)
|
||||||
+ texi_members(doc, what, base, variants, member_func)
|
+ texi_members(doc, what, base, variants, member_func)
|
||||||
+ texi_sections(doc))
|
+ texi_sections(doc, ifcond))
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
||||||
@ -204,47 +206,47 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
|||||||
def write(self, output_dir):
|
def write(self, output_dir):
|
||||||
self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
|
self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(TYPE_FMT(type='Enum',
|
self._gen.add(TYPE_FMT(type='Enum',
|
||||||
name=doc.symbol,
|
name=doc.symbol,
|
||||||
body=texi_entity(doc, 'Values',
|
body=texi_entity(doc, 'Values', ifcond,
|
||||||
member_func=texi_enum_value)))
|
member_func=texi_enum_value)))
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
if base and base.is_implicit():
|
if base and base.is_implicit():
|
||||||
base = None
|
base = None
|
||||||
self._gen.add(TYPE_FMT(type='Object',
|
self._gen.add(TYPE_FMT(type='Object',
|
||||||
name=doc.symbol,
|
name=doc.symbol,
|
||||||
body=texi_entity(doc, 'Members',
|
body=texi_entity(doc, 'Members', ifcond,
|
||||||
base, variants)))
|
base, variants)))
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(TYPE_FMT(type='Alternate',
|
self._gen.add(TYPE_FMT(type='Alternate',
|
||||||
name=doc.symbol,
|
name=doc.symbol,
|
||||||
body=texi_entity(doc, 'Members')))
|
body=texi_entity(doc, 'Members', ifcond)))
|
||||||
|
|
||||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig):
|
success_response, boxed, allow_oob, allow_preconfig):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
if boxed:
|
if boxed:
|
||||||
body = texi_body(doc)
|
body = texi_body(doc)
|
||||||
body += ('\n@b{Arguments:} the members of @code{%s}\n'
|
body += ('\n@b{Arguments:} the members of @code{%s}\n'
|
||||||
% arg_type.name)
|
% arg_type.name)
|
||||||
body += texi_sections(doc)
|
body += texi_sections(doc, ifcond)
|
||||||
else:
|
else:
|
||||||
body = texi_entity(doc, 'Arguments')
|
body = texi_entity(doc, 'Arguments', ifcond)
|
||||||
self._gen.add(MSG_FMT(type='Command',
|
self._gen.add(MSG_FMT(type='Command',
|
||||||
name=doc.symbol,
|
name=doc.symbol,
|
||||||
body=body))
|
body=body))
|
||||||
|
|
||||||
def visit_event(self, name, info, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(MSG_FMT(type='Event',
|
self._gen.add(MSG_FMT(type='Event',
|
||||||
name=doc.symbol,
|
name=doc.symbol,
|
||||||
body=texi_entity(doc, 'Arguments')))
|
body=texi_entity(doc, 'Arguments', ifcond)))
|
||||||
|
|
||||||
def symbol(self, doc, entity):
|
def symbol(self, doc, entity):
|
||||||
if self._gen._body:
|
if self._gen._body:
|
||||||
@ -257,7 +259,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
|||||||
assert not doc.args
|
assert not doc.args
|
||||||
if self._gen._body:
|
if self._gen._body:
|
||||||
self._gen.add('\n')
|
self._gen.add('\n')
|
||||||
self._gen.add(texi_body(doc) + texi_sections(doc))
|
self._gen.add(texi_body(doc) + texi_sections(doc, None))
|
||||||
|
|
||||||
|
|
||||||
def gen_doc(schema, output_dir, prefix):
|
def gen_doc(schema, output_dir, prefix):
|
||||||
|
@ -184,9 +184,11 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
|
|||||||
genh.add(gen_enum(self._enum_name, self._event_names))
|
genh.add(gen_enum(self._enum_name, self._event_names))
|
||||||
genc.add(gen_enum_lookup(self._enum_name, self._event_names))
|
genc.add(gen_enum_lookup(self._enum_name, self._event_names))
|
||||||
|
|
||||||
def visit_event(self, name, info, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||||
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name))
|
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
||||||
|
self._genc.add(gen_event_send(name, arg_type, boxed,
|
||||||
|
self._enum_name))
|
||||||
self._event_names.append(name)
|
self._event_names.append(name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,15 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
|||||||
def indent(level):
|
def indent(level):
|
||||||
return level * 4 * ' '
|
return level * 4 * ' '
|
||||||
|
|
||||||
|
if isinstance(obj, tuple):
|
||||||
|
ifobj, ifcond = obj
|
||||||
|
ret = gen_if(ifcond)
|
||||||
|
ret += to_qlit(ifobj, level)
|
||||||
|
endif = gen_endif(ifcond)
|
||||||
|
if endif:
|
||||||
|
ret += '\n' + endif
|
||||||
|
return ret
|
||||||
|
|
||||||
ret = ''
|
ret = ''
|
||||||
if not suppress_first_indent:
|
if not suppress_first_indent:
|
||||||
ret += indent(level)
|
ret += indent(level)
|
||||||
@ -26,11 +35,11 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
|||||||
elif isinstance(obj, str):
|
elif isinstance(obj, str):
|
||||||
ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
|
ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
|
||||||
elif isinstance(obj, list):
|
elif isinstance(obj, list):
|
||||||
elts = [to_qlit(elt, level + 1)
|
elts = [to_qlit(elt, level + 1).strip('\n')
|
||||||
for elt in obj]
|
for elt in obj]
|
||||||
elts.append(indent(level + 1) + "{}")
|
elts.append(indent(level + 1) + "{}")
|
||||||
ret += 'QLIT_QLIST(((QLitObject[]) {\n'
|
ret += 'QLIT_QLIST(((QLitObject[]) {\n'
|
||||||
ret += ',\n'.join(elts) + '\n'
|
ret += '\n'.join(elts) + '\n'
|
||||||
ret += indent(level) + '}))'
|
ret += indent(level) + '}))'
|
||||||
elif isinstance(obj, dict):
|
elif isinstance(obj, dict):
|
||||||
elts = []
|
elts = []
|
||||||
@ -45,6 +54,8 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
|
|||||||
ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
|
ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false')
|
||||||
else:
|
else:
|
||||||
assert False # not implemented
|
assert False # not implemented
|
||||||
|
if level > 0:
|
||||||
|
ret += ','
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@ -126,12 +137,12 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||||||
return '[' + self._use_type(typ.element_type) + ']'
|
return '[' + self._use_type(typ.element_type) + ']'
|
||||||
return self._name(typ.name)
|
return self._name(typ.name)
|
||||||
|
|
||||||
def _gen_qlit(self, name, mtype, obj):
|
def _gen_qlit(self, name, mtype, obj, ifcond):
|
||||||
if mtype not in ('command', 'event', 'builtin', 'array'):
|
if mtype not in ('command', 'event', 'builtin', 'array'):
|
||||||
name = self._name(name)
|
name = self._name(name)
|
||||||
obj['name'] = name
|
obj['name'] = name
|
||||||
obj['meta-type'] = mtype
|
obj['meta-type'] = mtype
|
||||||
self._qlits.append(obj)
|
self._qlits.append((obj, ifcond))
|
||||||
|
|
||||||
def _gen_member(self, member):
|
def _gen_member(self, member):
|
||||||
ret = {'name': member.name, 'type': self._use_type(member.type)}
|
ret = {'name': member.name, 'type': self._use_type(member.type)}
|
||||||
@ -147,28 +158,29 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||||||
return {'case': variant.name, 'type': self._use_type(variant.type)}
|
return {'case': variant.name, 'type': self._use_type(variant.type)}
|
||||||
|
|
||||||
def visit_builtin_type(self, name, info, json_type):
|
def visit_builtin_type(self, name, info, json_type):
|
||||||
self._gen_qlit(name, 'builtin', {'json-type': json_type})
|
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
self._gen_qlit(name, 'enum', {'values': values})
|
self._gen_qlit(name, 'enum', {'values': values}, ifcond)
|
||||||
|
|
||||||
def visit_array_type(self, name, info, element_type):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
element = self._use_type(element_type)
|
element = self._use_type(element_type)
|
||||||
self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
|
self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
|
||||||
|
ifcond)
|
||||||
|
|
||||||
def visit_object_type_flat(self, name, info, members, variants):
|
def visit_object_type_flat(self, name, info, ifcond, members, variants):
|
||||||
obj = {'members': [self._gen_member(m) for m in members]}
|
obj = {'members': [self._gen_member(m) for m in members]}
|
||||||
if variants:
|
if variants:
|
||||||
obj.update(self._gen_variants(variants.tag_member.name,
|
obj.update(self._gen_variants(variants.tag_member.name,
|
||||||
variants.variants))
|
variants.variants))
|
||||||
self._gen_qlit(name, 'object', obj)
|
self._gen_qlit(name, 'object', obj, ifcond)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
self._gen_qlit(name, 'alternate',
|
self._gen_qlit(name, 'alternate',
|
||||||
{'members': [{'type': self._use_type(m.type)}
|
{'members': [{'type': self._use_type(m.type)}
|
||||||
for m in variants.variants]})
|
for m in variants.variants]}, ifcond)
|
||||||
|
|
||||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig):
|
success_response, boxed, allow_oob, allow_preconfig):
|
||||||
arg_type = arg_type or self._schema.the_empty_object_type
|
arg_type = arg_type or self._schema.the_empty_object_type
|
||||||
ret_type = ret_type or self._schema.the_empty_object_type
|
ret_type = ret_type or self._schema.the_empty_object_type
|
||||||
@ -176,11 +188,12 @@ const QLitObject %(c_name)s = %(c_string)s;
|
|||||||
{'arg-type': self._use_type(arg_type),
|
{'arg-type': self._use_type(arg_type),
|
||||||
'ret-type': self._use_type(ret_type),
|
'ret-type': self._use_type(ret_type),
|
||||||
'allow-oob': allow_oob,
|
'allow-oob': allow_oob,
|
||||||
'allow-preconfig': allow_preconfig})
|
'allow-preconfig': allow_preconfig}, ifcond)
|
||||||
|
|
||||||
def visit_event(self, name, info, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||||
arg_type = arg_type or self._schema.the_empty_object_type
|
arg_type = arg_type or self._schema.the_empty_object_type
|
||||||
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
|
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
|
||||||
|
ifcond)
|
||||||
|
|
||||||
|
|
||||||
def gen_introspect(schema, output_dir, prefix, opt_unmask):
|
def gen_introspect(schema, output_dir, prefix, opt_unmask):
|
||||||
|
@ -55,7 +55,7 @@ def gen_struct_members(members):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def gen_object(name, base, members, variants):
|
def gen_object(name, ifcond, base, members, variants):
|
||||||
if name in objects_seen:
|
if name in objects_seen:
|
||||||
return ''
|
return ''
|
||||||
objects_seen.add(name)
|
objects_seen.add(name)
|
||||||
@ -64,11 +64,14 @@ def gen_object(name, base, members, variants):
|
|||||||
if variants:
|
if variants:
|
||||||
for v in variants.variants:
|
for v in variants.variants:
|
||||||
if isinstance(v.type, QAPISchemaObjectType):
|
if isinstance(v.type, QAPISchemaObjectType):
|
||||||
ret += gen_object(v.type.name, v.type.base,
|
ret += gen_object(v.type.name, v.type.ifcond, v.type.base,
|
||||||
v.type.local_members, v.type.variants)
|
v.type.local_members, v.type.variants)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
|
''')
|
||||||
|
ret += gen_if(ifcond)
|
||||||
|
ret += mcgen('''
|
||||||
struct %(c_name)s {
|
struct %(c_name)s {
|
||||||
''',
|
''',
|
||||||
c_name=c_name(name))
|
c_name=c_name(name))
|
||||||
@ -101,6 +104,7 @@ struct %(c_name)s {
|
|||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
};
|
};
|
||||||
''')
|
''')
|
||||||
|
ret += gen_endif(ifcond)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -208,34 +212,40 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
|||||||
self._genh.add(gen_type_cleanup_decl(name))
|
self._genh.add(gen_type_cleanup_decl(name))
|
||||||
self._genc.add(gen_type_cleanup(name))
|
self._genc.add(gen_type_cleanup(name))
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
self._genh.preamble_add(gen_enum(name, values, prefix))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
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):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genh.add(gen_array(name, element_type))
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||||
self._gen_type_cleanup(name)
|
self._genh.add(gen_array(name, element_type))
|
||||||
|
self._gen_type_cleanup(name)
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||||
# Nothing to do for the special empty builtin
|
# Nothing to do for the special empty builtin
|
||||||
if name == 'q_empty':
|
if name == 'q_empty':
|
||||||
return
|
return
|
||||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
with ifcontext(ifcond, self._genh):
|
||||||
self._genh.add(gen_object(name, base, members, variants))
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||||
if base and not base.is_implicit():
|
self._genh.add(gen_object(name, ifcond, base, members, variants))
|
||||||
self._genh.add(gen_upcast(name, base))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
# TODO Worth changing the visitor signature, so we could
|
if base and not base.is_implicit():
|
||||||
# directly use rather than repeat type.is_implicit()?
|
self._genh.add(gen_upcast(name, base))
|
||||||
if not name.startswith('q_'):
|
# TODO Worth changing the visitor signature, so we could
|
||||||
# implicit types won't be directly allocated/freed
|
# directly use rather than repeat type.is_implicit()?
|
||||||
self._gen_type_cleanup(name)
|
if not name.startswith('q_'):
|
||||||
|
# implicit types won't be directly allocated/freed
|
||||||
|
self._gen_type_cleanup(name)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
with ifcontext(ifcond, self._genh):
|
||||||
self._genh.add(gen_object(name, None,
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||||
|
self._genh.add(gen_object(name, ifcond, None,
|
||||||
[variants.tag_member], variants))
|
[variants.tag_member], variants))
|
||||||
self._gen_type_cleanup(name)
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
|
self._gen_type_cleanup(name)
|
||||||
|
|
||||||
|
|
||||||
def gen_types(schema, output_dir, prefix, opt_builtins):
|
def gen_types(schema, output_dir, prefix, opt_builtins):
|
||||||
|
@ -310,30 +310,35 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
|||||||
''',
|
''',
|
||||||
types=types))
|
types=types))
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
self._genh.add(gen_visit_decl(name, scalar=True))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
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):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
self._genh.add(gen_visit_decl(name))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genc.add(gen_visit_list(name, element_type))
|
self._genh.add(gen_visit_decl(name))
|
||||||
|
self._genc.add(gen_visit_list(name, element_type))
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||||
# Nothing to do for the special empty builtin
|
# Nothing to do for the special empty builtin
|
||||||
if name == 'q_empty':
|
if name == 'q_empty':
|
||||||
return
|
return
|
||||||
self._genh.add(gen_visit_members_decl(name))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genc.add(gen_visit_object_members(name, base, members, variants))
|
self._genh.add(gen_visit_members_decl(name))
|
||||||
# TODO Worth changing the visitor signature, so we could
|
self._genc.add(gen_visit_object_members(name, base,
|
||||||
# directly use rather than repeat type.is_implicit()?
|
members, variants))
|
||||||
if not name.startswith('q_'):
|
# TODO Worth changing the visitor signature, so we could
|
||||||
# only explicit types need an allocating visit
|
# directly use rather than repeat type.is_implicit()?
|
||||||
self._genh.add(gen_visit_decl(name))
|
if not name.startswith('q_'):
|
||||||
self._genc.add(gen_visit_object(name, base, members, variants))
|
# only explicit types need an allocating visit
|
||||||
|
self._genh.add(gen_visit_decl(name))
|
||||||
|
self._genc.add(gen_visit_object(name, base, members, variants))
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
self._genh.add(gen_visit_decl(name))
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genc.add(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):
|
def gen_visit(schema, output_dir, prefix, opt_builtins):
|
||||||
|
@ -442,6 +442,10 @@ qapi-schema += args-unknown.json
|
|||||||
qapi-schema += bad-base.json
|
qapi-schema += bad-base.json
|
||||||
qapi-schema += bad-data.json
|
qapi-schema += bad-data.json
|
||||||
qapi-schema += bad-ident.json
|
qapi-schema += bad-ident.json
|
||||||
|
qapi-schema += bad-if.json
|
||||||
|
qapi-schema += bad-if-empty.json
|
||||||
|
qapi-schema += bad-if-empty-list.json
|
||||||
|
qapi-schema += bad-if-list.json
|
||||||
qapi-schema += bad-type-bool.json
|
qapi-schema += bad-type-bool.json
|
||||||
qapi-schema += bad-type-dict.json
|
qapi-schema += bad-type-dict.json
|
||||||
qapi-schema += bad-type-int.json
|
qapi-schema += bad-type-int.json
|
||||||
|
1
tests/qapi-schema/bad-if-empty-list.err
Normal file
1
tests/qapi-schema/bad-if-empty-list.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/bad-if-empty-list.json:2: 'if' condition [] is useless
|
1
tests/qapi-schema/bad-if-empty-list.exit
Normal file
1
tests/qapi-schema/bad-if-empty-list.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
3
tests/qapi-schema/bad-if-empty-list.json
Normal file
3
tests/qapi-schema/bad-if-empty-list.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# check empty 'if' list
|
||||||
|
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': [] }
|
0
tests/qapi-schema/bad-if-empty-list.out
Normal file
0
tests/qapi-schema/bad-if-empty-list.out
Normal file
1
tests/qapi-schema/bad-if-empty.err
Normal file
1
tests/qapi-schema/bad-if-empty.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/bad-if-empty.json:2: 'if' condition '' makes no sense
|
1
tests/qapi-schema/bad-if-empty.exit
Normal file
1
tests/qapi-schema/bad-if-empty.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
3
tests/qapi-schema/bad-if-empty.json
Normal file
3
tests/qapi-schema/bad-if-empty.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# check empty 'if'
|
||||||
|
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': '' }
|
0
tests/qapi-schema/bad-if-empty.out
Normal file
0
tests/qapi-schema/bad-if-empty.out
Normal file
1
tests/qapi-schema/bad-if-list.err
Normal file
1
tests/qapi-schema/bad-if-list.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/bad-if-list.json:2: 'if' condition '' makes no sense
|
1
tests/qapi-schema/bad-if-list.exit
Normal file
1
tests/qapi-schema/bad-if-list.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
3
tests/qapi-schema/bad-if-list.json
Normal file
3
tests/qapi-schema/bad-if-list.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# check invalid 'if' content
|
||||||
|
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': ['foo', ''] }
|
0
tests/qapi-schema/bad-if-list.out
Normal file
0
tests/qapi-schema/bad-if-list.out
Normal file
1
tests/qapi-schema/bad-if.err
Normal file
1
tests/qapi-schema/bad-if.err
Normal file
@ -0,0 +1 @@
|
|||||||
|
tests/qapi-schema/bad-if.json:2: 'if' condition must be a string or a list of strings
|
1
tests/qapi-schema/bad-if.exit
Normal file
1
tests/qapi-schema/bad-if.exit
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
3
tests/qapi-schema/bad-if.json
Normal file
3
tests/qapi-schema/bad-if.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# check invalid 'if' type
|
||||||
|
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
|
0
tests/qapi-schema/bad-if.out
Normal file
0
tests/qapi-schema/bad-if.out
Normal file
@ -55,7 +55,7 @@
|
|||||||
#
|
#
|
||||||
# @two is undocumented
|
# @two is undocumented
|
||||||
##
|
##
|
||||||
{ 'enum': 'Enum', 'data': [ 'one', 'two' ] }
|
{ 'enum': 'Enum', 'data': [ 'one', 'two' ], 'if': 'defined(IFCOND)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @Base:
|
# @Base:
|
||||||
|
@ -3,6 +3,7 @@ enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
|
|||||||
prefix QTYPE
|
prefix QTYPE
|
||||||
module doc-good.json
|
module doc-good.json
|
||||||
enum Enum ['one', 'two']
|
enum Enum ['one', 'two']
|
||||||
|
if ['defined(IFCOND)']
|
||||||
object Base
|
object Base
|
||||||
member base1: Enum optional=False
|
member base1: Enum optional=False
|
||||||
object Variant1
|
object Variant1
|
||||||
|
@ -89,6 +89,8 @@ Not documented
|
|||||||
@end table
|
@end table
|
||||||
@code{two} is undocumented
|
@code{two} is undocumented
|
||||||
|
|
||||||
|
|
||||||
|
@b{If:} @code{defined(IFCOND)}
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@
|
|||||||
'data': { 'string0': 'str',
|
'data': { 'string0': 'str',
|
||||||
'dict1': 'UserDefTwoDict' } }
|
'dict1': 'UserDefTwoDict' } }
|
||||||
|
|
||||||
|
{ 'struct': 'UserDefThree',
|
||||||
|
'data': { 'string0': 'str' } }
|
||||||
|
|
||||||
# dummy struct to force generation of array types not otherwise mentioned
|
# dummy struct to force generation of array types not otherwise mentioned
|
||||||
{ 'struct': 'ForceArrays',
|
{ 'struct': 'ForceArrays',
|
||||||
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'],
|
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'],
|
||||||
@ -193,3 +196,26 @@
|
|||||||
'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
|
'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
|
||||||
'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
|
'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
|
||||||
'returns': '__org.qemu_x-Union1' }
|
'returns': '__org.qemu_x-Union1' }
|
||||||
|
|
||||||
|
# test 'if' condition handling
|
||||||
|
|
||||||
|
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||||
|
'if': 'defined(TEST_IF_STRUCT)' }
|
||||||
|
|
||||||
|
{ 'enum': 'TestIfEnum', 'data': [ 'foo', 'bar' ],
|
||||||
|
'if': 'defined(TEST_IF_ENUM)' }
|
||||||
|
|
||||||
|
{ 'union': 'TestIfUnion', 'data': { 'foo': 'TestStruct' },
|
||||||
|
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
|
||||||
|
|
||||||
|
{ 'alternate': 'TestIfAlternate', 'data': { 'foo': 'int', 'bar': 'TestStruct' },
|
||||||
|
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
|
||||||
|
|
||||||
|
{ 'command': 'TestIfCmd', 'data': { 'foo': 'TestIfStruct' },
|
||||||
|
'returns': 'UserDefThree',
|
||||||
|
'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
|
||||||
|
|
||||||
|
{ 'command': 'TestCmdReturnDefThree', 'returns': 'UserDefThree' }
|
||||||
|
|
||||||
|
{ 'event': 'TestIfEvent', 'data': { 'foo': 'TestIfStruct' },
|
||||||
|
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
|
||||||
|
@ -36,6 +36,8 @@ object UserDefTwoDict
|
|||||||
object UserDefTwo
|
object UserDefTwo
|
||||||
member string0: str optional=False
|
member string0: str optional=False
|
||||||
member dict1: UserDefTwoDict optional=False
|
member dict1: UserDefTwoDict optional=False
|
||||||
|
object UserDefThree
|
||||||
|
member string0: str optional=False
|
||||||
object ForceArrays
|
object ForceArrays
|
||||||
member unused1: UserDefOneList optional=False
|
member unused1: UserDefOneList optional=False
|
||||||
member unused2: UserDefTwoList optional=False
|
member unused2: UserDefTwoList optional=False
|
||||||
@ -233,3 +235,36 @@ object q_obj___org.qemu_x-command-arg
|
|||||||
member d: __org.qemu_x-Alt optional=False
|
member d: __org.qemu_x-Alt optional=False
|
||||||
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
|
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
|
||||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
|
object TestIfStruct
|
||||||
|
member foo: int optional=False
|
||||||
|
if ['defined(TEST_IF_STRUCT)']
|
||||||
|
enum TestIfEnum ['foo', 'bar']
|
||||||
|
if ['defined(TEST_IF_ENUM)']
|
||||||
|
object q_obj_TestStruct-wrapper
|
||||||
|
member data: TestStruct optional=False
|
||||||
|
enum TestIfUnionKind ['foo']
|
||||||
|
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
|
||||||
|
object TestIfUnion
|
||||||
|
member type: TestIfUnionKind optional=False
|
||||||
|
tag type
|
||||||
|
case foo: q_obj_TestStruct-wrapper
|
||||||
|
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
|
||||||
|
alternate TestIfAlternate
|
||||||
|
tag type
|
||||||
|
case foo: int
|
||||||
|
case bar: TestStruct
|
||||||
|
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
|
||||||
|
object q_obj_TestIfCmd-arg
|
||||||
|
member foo: TestIfStruct optional=False
|
||||||
|
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
|
||||||
|
command TestIfCmd q_obj_TestIfCmd-arg -> UserDefThree
|
||||||
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
|
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
|
||||||
|
command TestCmdReturnDefThree None -> UserDefThree
|
||||||
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
|
object q_obj_TestIfEvent-arg
|
||||||
|
member foo: TestIfStruct optional=False
|
||||||
|
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
|
||||||
|
event TestIfEvent q_obj_TestIfEvent-arg
|
||||||
|
boxed=False
|
||||||
|
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
|
||||||
|
@ -23,12 +23,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
|||||||
def visit_include(self, name, info):
|
def visit_include(self, name, info):
|
||||||
print('include %s' % name)
|
print('include %s' % name)
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||||
print('enum %s %s' % (name, values))
|
print('enum %s %s' % (name, values))
|
||||||
if prefix:
|
if prefix:
|
||||||
print(' prefix %s' % prefix)
|
print(' prefix %s' % prefix)
|
||||||
|
self._print_if(ifcond)
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, ifcond, base, members, variants):
|
||||||
print('object %s' % name)
|
print('object %s' % name)
|
||||||
if base:
|
if base:
|
||||||
print(' base %s' % base.name)
|
print(' base %s' % base.name)
|
||||||
@ -36,21 +37,25 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
|||||||
print(' member %s: %s optional=%s' % \
|
print(' member %s: %s optional=%s' % \
|
||||||
(m.name, m.type.name, m.optional))
|
(m.name, m.type.name, m.optional))
|
||||||
self._print_variants(variants)
|
self._print_variants(variants)
|
||||||
|
self._print_if(ifcond)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, variants):
|
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||||
print('alternate %s' % name)
|
print('alternate %s' % name)
|
||||||
self._print_variants(variants)
|
self._print_variants(variants)
|
||||||
|
self._print_if(ifcond)
|
||||||
|
|
||||||
def visit_command(self, name, info, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig):
|
success_response, boxed, allow_oob, allow_preconfig):
|
||||||
print('command %s %s -> %s' % \
|
print('command %s %s -> %s' % \
|
||||||
(name, arg_type and arg_type.name, ret_type and ret_type.name))
|
(name, arg_type and arg_type.name, ret_type and ret_type.name))
|
||||||
print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s' % \
|
print(' gen=%s success_response=%s boxed=%s oob=%s preconfig=%s' % \
|
||||||
(gen, success_response, boxed, allow_oob, allow_preconfig))
|
(gen, success_response, boxed, allow_oob, allow_preconfig))
|
||||||
|
self._print_if(ifcond)
|
||||||
|
|
||||||
def visit_event(self, name, info, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||||
print('event %s %s' % (name, arg_type and arg_type.name))
|
print('event %s %s' % (name, arg_type and arg_type.name))
|
||||||
print(' boxed=%s' % boxed)
|
print(' boxed=%s' % boxed)
|
||||||
|
self._print_if(ifcond)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _print_variants(variants):
|
def _print_variants(variants):
|
||||||
@ -59,6 +64,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
|||||||
for v in variants.variants:
|
for v in variants.variants:
|
||||||
print(' case %s: %s' % (v.name, v.type.name))
|
print(' case %s: %s' % (v.name, v.type.name))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _print_if(ifcond, indent=4):
|
||||||
|
if ifcond:
|
||||||
|
print('%sif %s' % (' ' * indent, ifcond))
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
schema = QAPISchema(sys.argv[1])
|
schema = QAPISchema(sys.argv[1])
|
||||||
|
@ -12,6 +12,18 @@
|
|||||||
|
|
||||||
static QmpCommandList qmp_commands;
|
static QmpCommandList qmp_commands;
|
||||||
|
|
||||||
|
#if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
|
||||||
|
UserDefThree *qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UserDefThree *qmp_TestCmdReturnDefThree(Error **errp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void qmp_user_def_cmd(Error **errp)
|
void qmp_user_def_cmd(Error **errp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
2
ui/vnc.h
2
ui/vnc.h
@ -297,7 +297,9 @@ struct VncState
|
|||||||
bool encode_ws;
|
bool encode_ws;
|
||||||
bool websocket;
|
bool websocket;
|
||||||
|
|
||||||
|
#ifdef CONFIG_VNC
|
||||||
VncClientInfo *info;
|
VncClientInfo *info;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Job thread bottom half has put data for a forced update
|
/* Job thread bottom half has put data for a forced update
|
||||||
* into the output buffer. This offset points to the end of
|
* into the output buffer. This offset points to the end of
|
||||||
|
Loading…
x
Reference in New Issue
Block a user