mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2018-12-13-v2' into staging
QAPI patches for 2018-12-13 # gpg: Signature made Fri 14 Dec 2018 05:53:51 GMT # 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-12-13-v2: (32 commits) qapi: add conditions to REPLICATION type/commands on the schema qapi: add more conditions to SPICE qapi: add condition to variants documentation qapi: add 'If:' condition to struct members documentation qapi: add 'If:' condition to enum values documentation qapi: Add #if conditions to generated code members qapi: add 'if' to alternate members qapi: add 'if' to union members qapi: Add 'if' to implicit struct members qapi: add a dictionary form for TYPE qapi-events: add 'if' condition to implicit event enum qapi: add 'if' to enum members qapi: add a dictionary form with 'name' key for enum members qapi: improve reporting of unknown or missing keys qapi: factor out checking for keys tests: print enum type members more like object type members qapi: change enum visitor and gen_enum* to take QAPISchemaMember qapi: Do not define enumeration value explicitly qapi: break long lines at 'data' member qapi: rename QAPISchemaEnumType.values to .members ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -26,7 +26,7 @@ how the schemas, scripts, and resulting code are used.
|
||||
== QMP/Guest agent schema ==
|
||||
|
||||
A QAPI schema file is designed to be loosely based on JSON
|
||||
(http://www.ietf.org/rfc/rfc7159.txt) with changes for quoting style
|
||||
(http://www.ietf.org/rfc/rfc8259.txt) with changes for quoting style
|
||||
and the use of comments; a QAPI schema file is then parsed by a python
|
||||
code generation program. A valid QAPI schema consists of a series of
|
||||
top-level expressions, with no commas between them. Where
|
||||
@@ -752,6 +752,25 @@ gets its generated code guarded like this:
|
||||
#endif /* defined(HAVE_BAR) */
|
||||
#endif /* defined(CONFIG_FOO) */
|
||||
|
||||
Where a member can be defined with a single string value for its type,
|
||||
it is also possible to supply a dictionary instead with both 'type'
|
||||
and 'if' keys.
|
||||
|
||||
Example: a conditional 'bar' member
|
||||
|
||||
{ 'struct': 'IfStruct', 'data':
|
||||
{ 'foo': 'int',
|
||||
'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } }
|
||||
|
||||
An enum value can be replaced by a dictionary with a 'name' and a 'if'
|
||||
key.
|
||||
|
||||
Example: a conditional 'bar' enum member.
|
||||
|
||||
{ 'enum': 'IfEnum', 'data':
|
||||
[ 'foo',
|
||||
{ 'name' : 'bar', 'if': 'defined(IFCOND)' } ] }
|
||||
|
||||
Please note that you are responsible to ensure that the C code will
|
||||
compile with an arbitrary combination of conditions, since the
|
||||
generators are unable to check it at this point.
|
||||
|
||||
@@ -32,7 +32,7 @@ following format:
|
||||
Where DATA-STRUCTURE-NAME is any valid JSON data structure, as defined
|
||||
by the JSON standard:
|
||||
|
||||
http://www.ietf.org/rfc/rfc7159.txt
|
||||
http://www.ietf.org/rfc/rfc8259.txt
|
||||
|
||||
The server expects its input to be encoded in UTF-8, and sends its
|
||||
output encoded in ASCII.
|
||||
|
||||
@@ -19,8 +19,8 @@ typedef struct StringInputVisitor StringInputVisitor;
|
||||
|
||||
/*
|
||||
* The string input visitor does not implement support for visiting
|
||||
* QAPI structs, alternates, null, or arbitrary QTypes. It also
|
||||
* requires a non-null list argument to visit_start_list().
|
||||
* QAPI structs, alternates, null, or arbitrary QTypes. Only flat lists
|
||||
* of integers (except type "size") are supported.
|
||||
*/
|
||||
Visitor *string_input_visitor_new(const char *str);
|
||||
|
||||
|
||||
@@ -146,14 +146,16 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
|
||||
int64_t *result);
|
||||
int qemu_strtou64(const char *nptr, const char **endptr, int base,
|
||||
uint64_t *result);
|
||||
int qemu_strtod(const char *nptr, const char **endptr, double *result);
|
||||
int qemu_strtod_finite(const char *nptr, const char **endptr, double *result);
|
||||
|
||||
int parse_uint(const char *s, unsigned long long *value, char **endptr,
|
||||
int base);
|
||||
int parse_uint_full(const char *s, unsigned long long *value, int base);
|
||||
|
||||
int qemu_strtosz(const char *nptr, char **end, uint64_t *result);
|
||||
int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result);
|
||||
int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result);
|
||||
int qemu_strtosz(const char *nptr, const char **end, uint64_t *result);
|
||||
int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result);
|
||||
int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result);
|
||||
|
||||
/* used to print char* safely */
|
||||
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
||||
|
||||
+4
-12
@@ -24,7 +24,9 @@
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "migration/failover.h"
|
||||
#ifdef CONFIG_REPLICATION
|
||||
#include "replication.h"
|
||||
#endif
|
||||
#include "net/colo-compare.h"
|
||||
#include "net/colo.h"
|
||||
#include "block/block.h"
|
||||
@@ -201,11 +203,11 @@ void colo_do_failover(MigrationState *s)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REPLICATION
|
||||
void qmp_xen_set_replication(bool enable, bool primary,
|
||||
bool has_failover, bool failover,
|
||||
Error **errp)
|
||||
{
|
||||
#ifdef CONFIG_REPLICATION
|
||||
ReplicationMode mode = primary ?
|
||||
REPLICATION_MODE_PRIMARY :
|
||||
REPLICATION_MODE_SECONDARY;
|
||||
@@ -224,14 +226,10 @@ void qmp_xen_set_replication(bool enable, bool primary,
|
||||
}
|
||||
replication_stop_all(failover, failover ? NULL : errp);
|
||||
}
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
|
||||
{
|
||||
#ifdef CONFIG_REPLICATION
|
||||
Error *err = NULL;
|
||||
ReplicationStatus *s = g_new0(ReplicationStatus, 1);
|
||||
|
||||
@@ -246,19 +244,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
|
||||
|
||||
error_free(err);
|
||||
return s;
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void qmp_xen_colo_do_checkpoint(Error **errp)
|
||||
{
|
||||
#ifdef CONFIG_REPLICATION
|
||||
replication_do_checkpoint_all(errp);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
COLOStatus *qmp_query_colo_status(Error **errp)
|
||||
{
|
||||
|
||||
@@ -1147,11 +1147,6 @@ static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
|
||||
*/
|
||||
static void qmp_unregister_commands_hack(void)
|
||||
{
|
||||
#ifndef CONFIG_REPLICATION
|
||||
qmp_unregister_command(&qmp_commands, "xen-set-replication");
|
||||
qmp_unregister_command(&qmp_commands, "query-xen-replication-status");
|
||||
qmp_unregister_command(&qmp_commands, "xen-colo-do-checkpoint");
|
||||
#endif
|
||||
#ifndef TARGET_I386
|
||||
qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection");
|
||||
qmp_unregister_command(&qmp_commands, "query-sev");
|
||||
@@ -3232,7 +3227,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
|
||||
{
|
||||
int ret;
|
||||
uint64_t val;
|
||||
char *end;
|
||||
const char *end;
|
||||
|
||||
while (qemu_isspace(*p)) {
|
||||
p++;
|
||||
|
||||
+17
-9
@@ -1143,8 +1143,10 @@
|
||||
# This command is now obsolete and will always return an error since 2.10
|
||||
#
|
||||
##
|
||||
{ 'command': 'block_passwd', 'data': {'*device': 'str',
|
||||
'*node-name': 'str', 'password': 'str'} }
|
||||
{ 'command': 'block_passwd',
|
||||
'data': { '*device': 'str',
|
||||
'*node-name': 'str',
|
||||
'password': 'str' } }
|
||||
|
||||
##
|
||||
# @block_resize:
|
||||
@@ -1171,9 +1173,10 @@
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'block_resize', 'data': { '*device': 'str',
|
||||
'*node-name': 'str',
|
||||
'size': 'int' }}
|
||||
{ 'command': 'block_resize',
|
||||
'data': { '*device': 'str',
|
||||
'*node-name': 'str',
|
||||
'size': 'int' } }
|
||||
|
||||
##
|
||||
# @NewImageMode:
|
||||
@@ -2620,7 +2623,9 @@
|
||||
'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
|
||||
'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
|
||||
'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
|
||||
'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
|
||||
'qcow2', 'qed', 'quorum', 'raw', 'rbd',
|
||||
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
|
||||
'sheepdog',
|
||||
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
|
||||
|
||||
##
|
||||
@@ -3377,7 +3382,8 @@
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
|
||||
{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsReplication:
|
||||
@@ -3395,7 +3401,8 @@
|
||||
{ 'struct': 'BlockdevOptionsReplication',
|
||||
'base': 'BlockdevOptionsGenericFormat',
|
||||
'data': { 'mode': 'ReplicationMode',
|
||||
'*top-id': 'str' } }
|
||||
'*top-id': 'str' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @NFSTransport:
|
||||
@@ -3711,7 +3718,8 @@
|
||||
'quorum': 'BlockdevOptionsQuorum',
|
||||
'raw': 'BlockdevOptionsRaw',
|
||||
'rbd': 'BlockdevOptionsRbd',
|
||||
'replication':'BlockdevOptionsReplication',
|
||||
'replication': { 'type': 'BlockdevOptionsReplication',
|
||||
'if': 'defined(CONFIG_REPLICATION)' },
|
||||
'sheepdog': 'BlockdevOptionsSheepdog',
|
||||
'ssh': 'BlockdevOptionsSsh',
|
||||
'throttle': 'BlockdevOptionsThrottle',
|
||||
|
||||
+85
-65
@@ -25,9 +25,10 @@
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'struct': 'ChardevInfo', 'data': {'label': 'str',
|
||||
'filename': 'str',
|
||||
'frontend-open': 'bool'} }
|
||||
{ 'struct': 'ChardevInfo',
|
||||
'data': { 'label': 'str',
|
||||
'filename': 'str',
|
||||
'frontend-open': 'bool' } }
|
||||
|
||||
##
|
||||
# @query-chardev:
|
||||
@@ -152,7 +153,8 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'ringbuf-write',
|
||||
'data': {'device': 'str', 'data': 'str',
|
||||
'data': { 'device': 'str',
|
||||
'data': 'str',
|
||||
'*format': 'DataFormat'} }
|
||||
|
||||
##
|
||||
@@ -202,8 +204,9 @@
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'struct': 'ChardevCommon', 'data': { '*logfile': 'str',
|
||||
'*logappend': 'bool' } }
|
||||
{ 'struct': 'ChardevCommon',
|
||||
'data': { '*logfile': 'str',
|
||||
'*logappend': 'bool' } }
|
||||
|
||||
##
|
||||
# @ChardevFile:
|
||||
@@ -217,9 +220,10 @@
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevFile', 'data': { '*in' : 'str',
|
||||
'out' : 'str',
|
||||
'*append': 'bool' },
|
||||
{ 'struct': 'ChardevFile',
|
||||
'data': { '*in': 'str',
|
||||
'out': 'str',
|
||||
'*append': 'bool' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -232,7 +236,8 @@
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevHostdev', 'data': { 'device' : 'str' },
|
||||
{ 'struct': 'ChardevHostdev',
|
||||
'data': { 'device': 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -260,15 +265,16 @@
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
|
||||
'*tls-creds' : 'str',
|
||||
'*server' : 'bool',
|
||||
'*wait' : 'bool',
|
||||
'*nodelay' : 'bool',
|
||||
'*telnet' : 'bool',
|
||||
'*tn3270' : 'bool',
|
||||
'*websocket' : 'bool',
|
||||
'*reconnect' : 'int' },
|
||||
{ 'struct': 'ChardevSocket',
|
||||
'data': { 'addr': 'SocketAddressLegacy',
|
||||
'*tls-creds': 'str',
|
||||
'*server': 'bool',
|
||||
'*wait': 'bool',
|
||||
'*nodelay': 'bool',
|
||||
'*telnet': 'bool',
|
||||
'*tn3270': 'bool',
|
||||
'*websocket': 'bool',
|
||||
'*reconnect': 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -281,8 +287,9 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevUdp', 'data': { 'remote' : 'SocketAddressLegacy',
|
||||
'*local' : 'SocketAddressLegacy' },
|
||||
{ 'struct': 'ChardevUdp',
|
||||
'data': { 'remote': 'SocketAddressLegacy',
|
||||
'*local': 'SocketAddressLegacy' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -294,7 +301,8 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevMux', 'data': { 'chardev' : 'str' },
|
||||
{ 'struct': 'ChardevMux',
|
||||
'data': { 'chardev': 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -308,7 +316,8 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevStdio', 'data': { '*signal' : 'bool' },
|
||||
{ 'struct': 'ChardevStdio',
|
||||
'data': { '*signal': 'bool' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
|
||||
@@ -321,9 +330,10 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
# TODO: 'if': 'defined(CONFIG_SPICE)'
|
||||
{ 'struct': 'ChardevSpiceChannel',
|
||||
'data': { 'type': 'str' },
|
||||
'base': 'ChardevCommon',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
|
||||
##
|
||||
# @ChardevSpicePort:
|
||||
@@ -334,9 +344,10 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
|
||||
'base': 'ChardevCommon' }
|
||||
# TODO: 'if': 'defined(CONFIG_SPICE)'
|
||||
{ 'struct': 'ChardevSpicePort',
|
||||
'data': { 'fqdn': 'str' },
|
||||
'base': 'ChardevCommon',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
|
||||
##
|
||||
# @ChardevVC:
|
||||
@@ -350,10 +361,11 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevVC', 'data': { '*width' : 'int',
|
||||
'*height' : 'int',
|
||||
'*cols' : 'int',
|
||||
'*rows' : 'int' },
|
||||
{ 'struct': 'ChardevVC',
|
||||
'data': { '*width': 'int',
|
||||
'*height': 'int',
|
||||
'*cols': 'int',
|
||||
'*rows': 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -365,7 +377,8 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'ChardevRingbuf', 'data': { '*size' : 'int' },
|
||||
{ 'struct': 'ChardevRingbuf',
|
||||
'data': { '*size': 'int' },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
##
|
||||
@@ -375,29 +388,30 @@
|
||||
#
|
||||
# Since: 1.4 (testdev since 2.2, wctablet since 2.9)
|
||||
##
|
||||
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
|
||||
'serial' : 'ChardevHostdev',
|
||||
'parallel': 'ChardevHostdev',
|
||||
'pipe' : 'ChardevHostdev',
|
||||
'socket' : 'ChardevSocket',
|
||||
'udp' : 'ChardevUdp',
|
||||
'pty' : 'ChardevCommon',
|
||||
'null' : 'ChardevCommon',
|
||||
'mux' : 'ChardevMux',
|
||||
'msmouse': 'ChardevCommon',
|
||||
'wctablet' : 'ChardevCommon',
|
||||
'braille': 'ChardevCommon',
|
||||
'testdev': 'ChardevCommon',
|
||||
'stdio' : 'ChardevStdio',
|
||||
'console': 'ChardevCommon',
|
||||
'spicevmc': 'ChardevSpiceChannel',
|
||||
# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
|
||||
'spiceport': 'ChardevSpicePort',
|
||||
# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
|
||||
'vc' : 'ChardevVC',
|
||||
'ringbuf': 'ChardevRingbuf',
|
||||
# next one is just for compatibility
|
||||
'memory' : 'ChardevRingbuf' } }
|
||||
{ 'union': 'ChardevBackend',
|
||||
'data': { 'file': 'ChardevFile',
|
||||
'serial': 'ChardevHostdev',
|
||||
'parallel': 'ChardevHostdev',
|
||||
'pipe': 'ChardevHostdev',
|
||||
'socket': 'ChardevSocket',
|
||||
'udp': 'ChardevUdp',
|
||||
'pty': 'ChardevCommon',
|
||||
'null': 'ChardevCommon',
|
||||
'mux': 'ChardevMux',
|
||||
'msmouse': 'ChardevCommon',
|
||||
'wctablet': 'ChardevCommon',
|
||||
'braille': 'ChardevCommon',
|
||||
'testdev': 'ChardevCommon',
|
||||
'stdio': 'ChardevStdio',
|
||||
'console': 'ChardevCommon',
|
||||
'spicevmc': { 'type': 'ChardevSpiceChannel',
|
||||
'if': 'defined(CONFIG_SPICE)' },
|
||||
'spiceport': { 'type': 'ChardevSpicePort',
|
||||
'if': 'defined(CONFIG_SPICE)' },
|
||||
'vc': 'ChardevVC',
|
||||
'ringbuf': 'ChardevRingbuf',
|
||||
# next one is just for compatibility
|
||||
'memory': 'ChardevRingbuf' } }
|
||||
|
||||
##
|
||||
# @ChardevReturn:
|
||||
@@ -409,7 +423,8 @@
|
||||
#
|
||||
# Since: 1.4
|
||||
##
|
||||
{ 'struct' : 'ChardevReturn', 'data': { '*pty' : 'str' } }
|
||||
{ 'struct' : 'ChardevReturn',
|
||||
'data': { '*pty': 'str' } }
|
||||
|
||||
##
|
||||
# @chardev-add:
|
||||
@@ -442,8 +457,9 @@
|
||||
# <- { "return": { "pty" : "/dev/pty/42" } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-add', 'data': {'id' : 'str',
|
||||
'backend' : 'ChardevBackend' },
|
||||
{ 'command': 'chardev-add',
|
||||
'data': { 'id': 'str',
|
||||
'backend': 'ChardevBackend' },
|
||||
'returns': 'ChardevReturn' }
|
||||
|
||||
##
|
||||
@@ -482,8 +498,9 @@
|
||||
# <- {"return": {}}
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-change', 'data': {'id' : 'str',
|
||||
'backend' : 'ChardevBackend' },
|
||||
{ 'command': 'chardev-change',
|
||||
'data': { 'id': 'str',
|
||||
'backend': 'ChardevBackend' },
|
||||
'returns': 'ChardevReturn' }
|
||||
|
||||
##
|
||||
@@ -503,7 +520,8 @@
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-remove', 'data': {'id': 'str'} }
|
||||
{ 'command': 'chardev-remove',
|
||||
'data': { 'id': 'str' } }
|
||||
|
||||
##
|
||||
# @chardev-send-break:
|
||||
@@ -522,7 +540,8 @@
|
||||
# <- { "return": {} }
|
||||
#
|
||||
##
|
||||
{ 'command': 'chardev-send-break', 'data': {'id': 'str'} }
|
||||
{ 'command': 'chardev-send-break',
|
||||
'data': { 'id': 'str' } }
|
||||
|
||||
##
|
||||
# @VSERPORT_CHANGE:
|
||||
@@ -543,4 +562,5 @@
|
||||
#
|
||||
##
|
||||
{ 'event': 'VSERPORT_CHANGE',
|
||||
'data': { 'id': 'str', 'open': 'bool' } }
|
||||
'data': { 'id': 'str',
|
||||
'open': 'bool' } }
|
||||
|
||||
+10
-5
@@ -1257,7 +1257,8 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'command': 'xen-set-replication',
|
||||
'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
|
||||
'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @ReplicationStatus:
|
||||
@@ -1272,7 +1273,8 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'ReplicationStatus',
|
||||
'data': { 'error': 'bool', '*desc': 'str' } }
|
||||
'data': { 'error': 'bool', '*desc': 'str' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @query-xen-replication-status:
|
||||
@@ -1289,7 +1291,8 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'command': 'query-xen-replication-status',
|
||||
'returns': 'ReplicationStatus' }
|
||||
'returns': 'ReplicationStatus',
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @xen-colo-do-checkpoint:
|
||||
@@ -1305,7 +1308,8 @@
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'command': 'xen-colo-do-checkpoint' }
|
||||
{ 'command': 'xen-colo-do-checkpoint',
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
|
||||
##
|
||||
# @COLOStatus:
|
||||
@@ -1356,7 +1360,8 @@
|
||||
#
|
||||
# Since: 3.0
|
||||
##
|
||||
{ 'command': 'migrate-recover', 'data': { 'uri': 'str' },
|
||||
{ 'command': 'migrate-recover',
|
||||
'data': { 'uri': 'str' },
|
||||
'allow-oob': true }
|
||||
|
||||
##
|
||||
|
||||
+5
-2
@@ -2385,7 +2385,9 @@
|
||||
# <- { "return": { "fdset-id": 1, "fd": 3 } }
|
||||
#
|
||||
##
|
||||
{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
|
||||
{ 'command': 'add-fd',
|
||||
'data': { '*fdset-id': 'int',
|
||||
'*opaque': 'str' },
|
||||
'returns': 'AddfdInfo' }
|
||||
|
||||
##
|
||||
@@ -2657,7 +2659,8 @@
|
||||
# }
|
||||
#
|
||||
##
|
||||
{'command': 'query-command-line-options', 'data': { '*option': 'str' },
|
||||
{'command': 'query-command-line-options',
|
||||
'data': { '*option': 'str' },
|
||||
'returns': ['CommandLineOptionInfo'],
|
||||
'allow-preconfig': true }
|
||||
|
||||
|
||||
+2
-1
@@ -657,7 +657,8 @@
|
||||
# }
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
|
||||
{ 'command': 'query-rx-filter',
|
||||
'data': { '*name': 'str' },
|
||||
'returns': ['RxFilterInfo'] }
|
||||
|
||||
##
|
||||
|
||||
@@ -562,19 +562,20 @@ static void qobject_input_type_number_keyval(Visitor *v, const char *name,
|
||||
{
|
||||
QObjectInputVisitor *qiv = to_qiv(v);
|
||||
const char *str = qobject_input_get_keyval(qiv, name, errp);
|
||||
char *endp;
|
||||
double val;
|
||||
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
*obj = strtod(str, &endp);
|
||||
if (errno || endp == str || *endp || !isfinite(*obj)) {
|
||||
if (qemu_strtod_finite(str, NULL, &val)) {
|
||||
/* TODO report -ERANGE more nicely */
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
|
||||
full_name(qiv, name), "number");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = val;
|
||||
}
|
||||
|
||||
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
|
||||
|
||||
+230
-181
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -76,8 +76,9 @@
|
||||
#
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
|
||||
'*cancel-path' : 'str'} }
|
||||
{ 'struct': 'TPMPassthroughOptions',
|
||||
'data': { '*path': 'str',
|
||||
'*cancel-path': 'str' } }
|
||||
|
||||
##
|
||||
# @TPMEmulatorOptions:
|
||||
|
||||
+2
-1
@@ -598,7 +598,8 @@
|
||||
# Notes: An empty password in this command will set the password to the empty
|
||||
# string. Existing clients are unaffected by executing this command.
|
||||
##
|
||||
{ 'command': 'change-vnc-password', 'data': {'password': 'str'},
|
||||
{ 'command': 'change-vnc-password',
|
||||
'data': { 'password': 'str' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
|
||||
##
|
||||
|
||||
@@ -288,6 +288,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (qdict_haskey(dict, qstring_get_str(key))) {
|
||||
parse_error(ctxt, token, "duplicate key");
|
||||
goto out;
|
||||
}
|
||||
|
||||
qdict_put_obj(dict, qstring_get_str(key), value);
|
||||
|
||||
qobject_unref(key);
|
||||
|
||||
+133
-74
@@ -588,11 +588,11 @@ def discriminator_find_enum_define(expr):
|
||||
if not base_members:
|
||||
return None
|
||||
|
||||
discriminator_type = base_members.get(discriminator)
|
||||
if not discriminator_type:
|
||||
discriminator_value = base_members.get(discriminator)
|
||||
if not discriminator_value:
|
||||
return None
|
||||
|
||||
return enum_types.get(discriminator_type)
|
||||
return enum_types.get(discriminator_value['type'])
|
||||
|
||||
|
||||
# Names must be letters, numbers, -, and _. They must start with letter,
|
||||
@@ -704,8 +704,10 @@ def check_type(info, source, value, allow_array=False,
|
||||
% (source, key))
|
||||
# Todo: allow dictionaries to represent default values of
|
||||
# an optional argument.
|
||||
check_type(info, "Member '%s' of %s" % (key, source), arg,
|
||||
allow_array=True,
|
||||
check_known_keys(info, "member '%s' of %s" % (key, source),
|
||||
arg, ['type'], ['if'])
|
||||
check_type(info, "Member '%s' of %s" % (key, source),
|
||||
arg['type'], allow_array=True,
|
||||
allow_metas=['built-in', 'union', 'alternate', 'struct',
|
||||
'enum'])
|
||||
|
||||
@@ -740,6 +742,10 @@ def check_event(expr, info):
|
||||
allow_metas=meta)
|
||||
|
||||
|
||||
def enum_get_names(expr):
|
||||
return [e['name'] for e in expr['data']]
|
||||
|
||||
|
||||
def check_union(expr, info):
|
||||
name = expr['union']
|
||||
base = expr.get('base')
|
||||
@@ -772,13 +778,17 @@ def check_union(expr, info):
|
||||
# member of the base struct.
|
||||
check_name(info, "Discriminator of flat union '%s'" % name,
|
||||
discriminator)
|
||||
discriminator_type = base_members.get(discriminator)
|
||||
if not discriminator_type:
|
||||
discriminator_value = base_members.get(discriminator)
|
||||
if not discriminator_value:
|
||||
raise QAPISemError(info,
|
||||
"Discriminator '%s' is not a member of base "
|
||||
"struct '%s'"
|
||||
% (discriminator, base))
|
||||
enum_define = enum_types.get(discriminator_type)
|
||||
if discriminator_value.get('if'):
|
||||
raise QAPISemError(info, 'The discriminator %s.%s for union %s '
|
||||
'must not be conditional' %
|
||||
(base, discriminator, name))
|
||||
enum_define = enum_types.get(discriminator_value['type'])
|
||||
allow_metas = ['struct']
|
||||
# Do not allow string discriminator
|
||||
if not enum_define:
|
||||
@@ -792,14 +802,17 @@ def check_union(expr, info):
|
||||
for (key, value) in members.items():
|
||||
check_name(info, "Member of union '%s'" % name, key)
|
||||
|
||||
check_known_keys(info, "member '%s' of union '%s'" % (key, name),
|
||||
value, ['type'], ['if'])
|
||||
# Each value must name a known type
|
||||
check_type(info, "Member '%s' of union '%s'" % (key, name),
|
||||
value, allow_array=not base, allow_metas=allow_metas)
|
||||
value['type'],
|
||||
allow_array=not base, allow_metas=allow_metas)
|
||||
|
||||
# If the discriminator names an enum type, then all members
|
||||
# of 'data' must also be members of the enum type.
|
||||
if enum_define:
|
||||
if key not in enum_define['data']:
|
||||
if key not in enum_get_names(enum_define):
|
||||
raise QAPISemError(info,
|
||||
"Discriminator value '%s' is not found in "
|
||||
"enum '%s'"
|
||||
@@ -818,20 +831,23 @@ def check_alternate(expr, info):
|
||||
"in 'data'" % name)
|
||||
for (key, value) in members.items():
|
||||
check_name(info, "Member of alternate '%s'" % name, key)
|
||||
check_known_keys(info,
|
||||
"member '%s' of alternate '%s'" % (key, name),
|
||||
value, ['type'], ['if'])
|
||||
typ = value['type']
|
||||
|
||||
# Ensure alternates have no type conflicts.
|
||||
check_type(info, "Member '%s' of alternate '%s'" % (key, name),
|
||||
value,
|
||||
check_type(info, "Member '%s' of alternate '%s'" % (key, name), typ,
|
||||
allow_metas=['built-in', 'union', 'struct', 'enum'])
|
||||
qtype = find_alternate_member_qtype(value)
|
||||
qtype = find_alternate_member_qtype(typ)
|
||||
if not qtype:
|
||||
raise QAPISemError(info, "Alternate '%s' member '%s' cannot use "
|
||||
"type '%s'" % (name, key, value))
|
||||
"type '%s'" % (name, key, typ))
|
||||
conflicting = set([qtype])
|
||||
if qtype == 'QTYPE_QSTRING':
|
||||
enum_expr = enum_types.get(value)
|
||||
enum_expr = enum_types.get(typ)
|
||||
if enum_expr:
|
||||
for v in enum_expr['data']:
|
||||
for v in enum_get_names(enum_expr):
|
||||
if v in ['on', 'off']:
|
||||
conflicting.add('QTYPE_QBOOL')
|
||||
if re.match(r'[-+0-9.]', v): # lazy, could be tightened
|
||||
@@ -849,7 +865,7 @@ def check_alternate(expr, info):
|
||||
|
||||
def check_enum(expr, info):
|
||||
name = expr['enum']
|
||||
members = expr.get('data')
|
||||
members = expr['data']
|
||||
prefix = expr.get('prefix')
|
||||
|
||||
if not isinstance(members, list):
|
||||
@@ -858,8 +874,12 @@ def check_enum(expr, info):
|
||||
if prefix is not None and not isinstance(prefix, str):
|
||||
raise QAPISemError(info,
|
||||
"Enum '%s' requires a string for 'prefix'" % name)
|
||||
|
||||
for member in members:
|
||||
check_name(info, "Member of enum '%s'" % name, member,
|
||||
source = "dictionary member of enum '%s'" % name
|
||||
check_known_keys(info, source, member, ['name'], ['if'])
|
||||
check_if(member, info)
|
||||
check_name(info, "Member of enum '%s'" % name, member['name'],
|
||||
enum_member=True)
|
||||
|
||||
|
||||
@@ -873,6 +893,24 @@ def check_struct(expr, info):
|
||||
allow_metas=['struct'])
|
||||
|
||||
|
||||
def check_known_keys(info, source, keys, required, optional):
|
||||
|
||||
def pprint(elems):
|
||||
return ', '.join("'" + e + "'" for e in sorted(elems))
|
||||
|
||||
missing = set(required) - set(keys)
|
||||
if missing:
|
||||
raise QAPISemError(info, "Key%s %s %s missing from %s"
|
||||
% ('s' if len(missing) > 1 else '', pprint(missing),
|
||||
'are' if len(missing) > 1 else 'is', source))
|
||||
allowed = set(required + optional)
|
||||
unknown = set(keys) - allowed
|
||||
if unknown:
|
||||
raise QAPISemError(info, "Unknown key%s %s in %s\nValid keys are %s."
|
||||
% ('s' if len(unknown) > 1 else '', pprint(unknown),
|
||||
source, pprint(allowed)))
|
||||
|
||||
|
||||
def check_keys(expr_elem, meta, required, optional=[]):
|
||||
expr = expr_elem['expr']
|
||||
info = expr_elem['info']
|
||||
@@ -880,10 +918,9 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
||||
if not isinstance(name, str):
|
||||
raise QAPISemError(info, "'%s' key must have a string value" % meta)
|
||||
required = required + [meta]
|
||||
source = "%s '%s'" % (meta, name)
|
||||
check_known_keys(info, source, expr.keys(), required, optional)
|
||||
for (key, value) in expr.items():
|
||||
if key not in required and key not in optional:
|
||||
raise QAPISemError(info, "Unknown key '%s' in %s '%s'"
|
||||
% (key, meta, name))
|
||||
if key in ['gen', 'success-response'] and value is not False:
|
||||
raise QAPISemError(info,
|
||||
"'%s' of %s '%s' should only use false value"
|
||||
@@ -895,10 +932,20 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
||||
% (key, meta, name))
|
||||
if key == 'if':
|
||||
check_if(expr, info)
|
||||
for key in required:
|
||||
if key not in expr:
|
||||
raise QAPISemError(info, "Key '%s' is missing from %s '%s'"
|
||||
% (key, meta, name))
|
||||
|
||||
|
||||
def normalize_enum(expr):
|
||||
if isinstance(expr['data'], list):
|
||||
expr['data'] = [m if isinstance(m, dict) else {'name': m}
|
||||
for m in expr['data']]
|
||||
|
||||
|
||||
def normalize_members(members):
|
||||
if isinstance(members, OrderedDict):
|
||||
for key, arg in members.items():
|
||||
if isinstance(arg, dict):
|
||||
continue
|
||||
members[key] = {'type': arg}
|
||||
|
||||
|
||||
def check_exprs(exprs):
|
||||
@@ -924,27 +971,34 @@ def check_exprs(exprs):
|
||||
if 'enum' in expr:
|
||||
meta = 'enum'
|
||||
check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix'])
|
||||
normalize_enum(expr)
|
||||
enum_types[expr[meta]] = expr
|
||||
elif 'union' in expr:
|
||||
meta = 'union'
|
||||
check_keys(expr_elem, 'union', ['data'],
|
||||
['base', 'discriminator', 'if'])
|
||||
normalize_members(expr.get('base'))
|
||||
normalize_members(expr['data'])
|
||||
union_types[expr[meta]] = expr
|
||||
elif 'alternate' in expr:
|
||||
meta = 'alternate'
|
||||
check_keys(expr_elem, 'alternate', ['data'], ['if'])
|
||||
normalize_members(expr['data'])
|
||||
elif 'struct' in expr:
|
||||
meta = 'struct'
|
||||
check_keys(expr_elem, 'struct', ['data'], ['base', 'if'])
|
||||
normalize_members(expr['data'])
|
||||
struct_types[expr[meta]] = expr
|
||||
elif 'command' in expr:
|
||||
meta = 'command'
|
||||
check_keys(expr_elem, 'command', [],
|
||||
['data', 'returns', 'gen', 'success-response',
|
||||
'boxed', 'allow-oob', 'allow-preconfig', 'if'])
|
||||
normalize_members(expr.get('data'))
|
||||
elif 'event' in expr:
|
||||
meta = 'event'
|
||||
check_keys(expr_elem, 'event', [], ['data', 'boxed', 'if'])
|
||||
normalize_members(expr.get('data'))
|
||||
else:
|
||||
raise QAPISemError(expr_elem['info'],
|
||||
"Expression is missing metatype")
|
||||
@@ -1063,7 +1117,7 @@ class QAPISchemaVisitor(object):
|
||||
def visit_builtin_type(self, name, info, json_type):
|
||||
pass
|
||||
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
||||
pass
|
||||
|
||||
def visit_array_type(self, name, info, ifcond, element_type):
|
||||
@@ -1161,22 +1215,22 @@ class QAPISchemaBuiltinType(QAPISchemaType):
|
||||
|
||||
|
||||
class QAPISchemaEnumType(QAPISchemaType):
|
||||
def __init__(self, name, info, doc, ifcond, values, prefix):
|
||||
def __init__(self, name, info, doc, ifcond, members, prefix):
|
||||
QAPISchemaType.__init__(self, name, info, doc, ifcond)
|
||||
for v in values:
|
||||
assert isinstance(v, QAPISchemaMember)
|
||||
v.set_owner(name)
|
||||
for m in members:
|
||||
assert isinstance(m, QAPISchemaMember)
|
||||
m.set_owner(name)
|
||||
assert prefix is None or isinstance(prefix, str)
|
||||
self.values = values
|
||||
self.members = members
|
||||
self.prefix = prefix
|
||||
|
||||
def check(self, schema):
|
||||
QAPISchemaType.check(self, schema)
|
||||
seen = {}
|
||||
for v in self.values:
|
||||
v.check_clash(self.info, seen)
|
||||
for m in self.members:
|
||||
m.check_clash(self.info, seen)
|
||||
if self.doc:
|
||||
self.doc.connect_member(v)
|
||||
self.doc.connect_member(m)
|
||||
|
||||
def is_implicit(self):
|
||||
# See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
|
||||
@@ -1186,14 +1240,14 @@ class QAPISchemaEnumType(QAPISchemaType):
|
||||
return c_name(self.name)
|
||||
|
||||
def member_names(self):
|
||||
return [v.name for v in self.values]
|
||||
return [m.name for m in self.members]
|
||||
|
||||
def json_type(self):
|
||||
return 'string'
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_enum_type(self.name, self.info, self.ifcond,
|
||||
self.member_names(), self.prefix)
|
||||
self.members, self.prefix)
|
||||
|
||||
|
||||
class QAPISchemaArrayType(QAPISchemaType):
|
||||
@@ -1318,9 +1372,10 @@ class QAPISchemaObjectType(QAPISchemaType):
|
||||
class QAPISchemaMember(object):
|
||||
role = 'member'
|
||||
|
||||
def __init__(self, name):
|
||||
def __init__(self, name, ifcond=None):
|
||||
assert isinstance(name, str)
|
||||
self.name = name
|
||||
self.ifcond = listify_cond(ifcond)
|
||||
self.owner = None
|
||||
|
||||
def set_owner(self, name):
|
||||
@@ -1361,8 +1416,8 @@ class QAPISchemaMember(object):
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeMember(QAPISchemaMember):
|
||||
def __init__(self, name, typ, optional):
|
||||
QAPISchemaMember.__init__(self, name)
|
||||
def __init__(self, name, typ, optional, ifcond=None):
|
||||
QAPISchemaMember.__init__(self, name, ifcond)
|
||||
assert isinstance(typ, str)
|
||||
assert isinstance(optional, bool)
|
||||
self._type_name = typ
|
||||
@@ -1403,9 +1458,9 @@ class QAPISchemaObjectTypeVariants(object):
|
||||
if self._tag_name: # flat union
|
||||
# branches that are not explicitly covered get an empty type
|
||||
cases = set([v.name for v in self.variants])
|
||||
for val in self.tag_member.type.values:
|
||||
if val.name not in cases:
|
||||
v = QAPISchemaObjectTypeVariant(val.name, 'q_empty')
|
||||
for m in self.tag_member.type.members:
|
||||
if m.name not in cases:
|
||||
v = QAPISchemaObjectTypeVariant(m.name, 'q_empty')
|
||||
v.set_owner(self.tag_member.owner)
|
||||
self.variants.append(v)
|
||||
for v in self.variants:
|
||||
@@ -1428,8 +1483,8 @@ class QAPISchemaObjectTypeVariants(object):
|
||||
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
||||
role = 'branch'
|
||||
|
||||
def __init__(self, name, typ):
|
||||
QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
|
||||
def __init__(self, name, typ, ifcond=None):
|
||||
QAPISchemaObjectTypeMember.__init__(self, name, typ, False, ifcond)
|
||||
|
||||
|
||||
class QAPISchemaAlternateType(QAPISchemaType):
|
||||
@@ -1620,14 +1675,16 @@ class QAPISchema(object):
|
||||
self.the_empty_object_type = QAPISchemaObjectType(
|
||||
'q_empty', None, None, None, None, [], None)
|
||||
self._def_entity(self.the_empty_object_type)
|
||||
qtype_values = self._make_enum_members(['none', 'qnull', 'qnum',
|
||||
'qstring', 'qdict', 'qlist',
|
||||
'qbool'])
|
||||
|
||||
qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
|
||||
'qbool']
|
||||
qtype_values = self._make_enum_members([{'name': n} for n in qtypes])
|
||||
|
||||
self._def_entity(QAPISchemaEnumType('QType', None, None, None,
|
||||
qtype_values, 'QTYPE'))
|
||||
|
||||
def _make_enum_members(self, values):
|
||||
return [QAPISchemaMember(v) for v in values]
|
||||
return [QAPISchemaMember(v['name'], v.get('if')) for v in values]
|
||||
|
||||
def _make_implicit_enum_type(self, name, info, ifcond, values):
|
||||
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
||||
@@ -1674,7 +1731,7 @@ class QAPISchema(object):
|
||||
name, info, doc, ifcond,
|
||||
self._make_enum_members(data), prefix))
|
||||
|
||||
def _make_member(self, name, typ, info):
|
||||
def _make_member(self, name, typ, ifcond, info):
|
||||
optional = False
|
||||
if name.startswith('*'):
|
||||
name = name[1:]
|
||||
@@ -1682,10 +1739,10 @@ class QAPISchema(object):
|
||||
if isinstance(typ, list):
|
||||
assert len(typ) == 1
|
||||
typ = self._make_array_type(typ[0], info)
|
||||
return QAPISchemaObjectTypeMember(name, typ, optional)
|
||||
return QAPISchemaObjectTypeMember(name, typ, optional, ifcond)
|
||||
|
||||
def _make_members(self, data, info):
|
||||
return [self._make_member(key, value, info)
|
||||
return [self._make_member(key, value['type'], value.get('if'), info)
|
||||
for (key, value) in data.items()]
|
||||
|
||||
def _def_struct_type(self, expr, info, doc):
|
||||
@@ -1697,17 +1754,17 @@ class QAPISchema(object):
|
||||
self._make_members(data, info),
|
||||
None))
|
||||
|
||||
def _make_variant(self, case, typ):
|
||||
return QAPISchemaObjectTypeVariant(case, typ)
|
||||
def _make_variant(self, case, typ, ifcond):
|
||||
return QAPISchemaObjectTypeVariant(case, typ, ifcond)
|
||||
|
||||
def _make_simple_variant(self, case, typ, info):
|
||||
def _make_simple_variant(self, case, typ, ifcond, info):
|
||||
if isinstance(typ, list):
|
||||
assert len(typ) == 1
|
||||
typ = self._make_array_type(typ[0], info)
|
||||
typ = self._make_implicit_object_type(
|
||||
typ, info, None, self.lookup_type(typ),
|
||||
'wrapper', [self._make_member('data', typ, info)])
|
||||
return QAPISchemaObjectTypeVariant(case, typ)
|
||||
'wrapper', [self._make_member('data', typ, None, info)])
|
||||
return QAPISchemaObjectTypeVariant(case, typ, ifcond)
|
||||
|
||||
def _def_union_type(self, expr, info, doc):
|
||||
name = expr['union']
|
||||
@@ -1721,14 +1778,15 @@ class QAPISchema(object):
|
||||
name, info, doc, ifcond,
|
||||
'base', self._make_members(base, info))
|
||||
if tag_name:
|
||||
variants = [self._make_variant(key, value)
|
||||
variants = [self._make_variant(key, value['type'], value.get('if'))
|
||||
for (key, value) in data.items()]
|
||||
members = []
|
||||
else:
|
||||
variants = [self._make_simple_variant(key, value, info)
|
||||
variants = [self._make_simple_variant(key, value['type'],
|
||||
value.get('if'), info)
|
||||
for (key, value) in data.items()]
|
||||
typ = self._make_implicit_enum_type(name, info, ifcond,
|
||||
[v.name for v in variants])
|
||||
enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
|
||||
typ = self._make_implicit_enum_type(name, info, ifcond, enum)
|
||||
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
|
||||
members = [tag_member]
|
||||
self._def_entity(
|
||||
@@ -1741,7 +1799,7 @@ class QAPISchema(object):
|
||||
name = expr['alternate']
|
||||
data = expr['data']
|
||||
ifcond = expr.get('if')
|
||||
variants = [self._make_variant(key, value)
|
||||
variants = [self._make_variant(key, value['type'], value.get('if'))
|
||||
for (key, value) in data.items()]
|
||||
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
|
||||
self._def_entity(
|
||||
@@ -2012,19 +2070,21 @@ def _wrap_ifcond(ifcond, before, after):
|
||||
return out
|
||||
|
||||
|
||||
def gen_enum_lookup(name, values, prefix=None):
|
||||
def gen_enum_lookup(name, members, prefix=None):
|
||||
ret = mcgen('''
|
||||
|
||||
const QEnumLookup %(c_name)s_lookup = {
|
||||
.array = (const char *const[]) {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
for value in values:
|
||||
index = c_enum_const(name, value, prefix)
|
||||
for m in members:
|
||||
ret += gen_if(m.ifcond)
|
||||
index = c_enum_const(name, m.name, prefix)
|
||||
ret += mcgen('''
|
||||
[%(index)s] = "%(value)s",
|
||||
[%(index)s] = "%(name)s",
|
||||
''',
|
||||
index=index, value=value)
|
||||
index=index, name=m.name)
|
||||
ret += gen_endif(m.ifcond)
|
||||
|
||||
ret += mcgen('''
|
||||
},
|
||||
@@ -2035,9 +2095,9 @@ const QEnumLookup %(c_name)s_lookup = {
|
||||
return ret
|
||||
|
||||
|
||||
def gen_enum(name, values, prefix=None):
|
||||
def gen_enum(name, members, prefix=None):
|
||||
# append automatically generated _MAX value
|
||||
enum_values = values + ['_MAX']
|
||||
enum_members = members + [QAPISchemaMember('_MAX')]
|
||||
|
||||
ret = mcgen('''
|
||||
|
||||
@@ -2045,14 +2105,13 @@ typedef enum %(c_name)s {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
|
||||
i = 0
|
||||
for value in enum_values:
|
||||
for m in enum_members:
|
||||
ret += gen_if(m.ifcond)
|
||||
ret += mcgen('''
|
||||
%(c_enum)s = %(i)d,
|
||||
%(c_enum)s,
|
||||
''',
|
||||
c_enum=c_enum_const(name, value, prefix),
|
||||
i=i)
|
||||
i += 1
|
||||
c_enum=c_enum_const(name, m.name, prefix))
|
||||
ret += gen_endif(m.ifcond)
|
||||
|
||||
ret += mcgen('''
|
||||
} %(c_name)s;
|
||||
|
||||
+19
-12
@@ -126,19 +126,27 @@ def texi_body(doc):
|
||||
return texi_format(doc.body.text)
|
||||
|
||||
|
||||
def texi_enum_value(value):
|
||||
def texi_if(ifcond, prefix='\n', suffix='\n'):
|
||||
"""Format the #if condition"""
|
||||
if not ifcond:
|
||||
return ''
|
||||
return '%s@b{If:} @code{%s}%s' % (prefix, ', '.join(ifcond), suffix)
|
||||
|
||||
|
||||
def texi_enum_value(value, desc, suffix):
|
||||
"""Format a table of members item for an enumeration value"""
|
||||
return '@item @code{%s}\n' % value.name
|
||||
return '@item @code{%s}\n%s%s' % (
|
||||
value.name, desc, texi_if(value.ifcond, prefix='@*'))
|
||||
|
||||
|
||||
def texi_member(member, suffix=''):
|
||||
def texi_member(member, desc, suffix):
|
||||
"""Format a table of members item for an object type member"""
|
||||
typ = member.type.doc_type()
|
||||
membertype = ': ' + typ if typ else ''
|
||||
return '@item @code{%s%s}%s%s\n' % (
|
||||
return '@item @code{%s%s}%s%s\n%s%s' % (
|
||||
member.name, membertype,
|
||||
' (optional)' if member.optional else '',
|
||||
suffix)
|
||||
suffix, desc, texi_if(member.ifcond, prefix='@*'))
|
||||
|
||||
|
||||
def texi_members(doc, what, base, variants, member_func):
|
||||
@@ -155,17 +163,17 @@ def texi_members(doc, what, base, variants, member_func):
|
||||
desc = 'One of ' + members_text + '\n'
|
||||
else:
|
||||
desc = 'Not documented\n'
|
||||
items += member_func(section.member) + desc
|
||||
items += member_func(section.member, desc, suffix='')
|
||||
if base:
|
||||
items += '@item The members of @code{%s}\n' % base.doc_type()
|
||||
if variants:
|
||||
for v in variants.variants:
|
||||
when = ' when @code{%s} is @t{"%s"}' % (
|
||||
variants.tag_member.name, v.name)
|
||||
when = ' when @code{%s} is @t{"%s"}%s' % (
|
||||
variants.tag_member.name, v.name, texi_if(v.ifcond, " (", ")"))
|
||||
if v.type.is_implicit():
|
||||
assert not v.type.base and not v.type.variants
|
||||
for m in v.type.local_members:
|
||||
items += member_func(m, when)
|
||||
items += member_func(m, desc='', suffix=when)
|
||||
else:
|
||||
items += '@item The members of @code{%s}%s\n' % (
|
||||
v.type.doc_type(), when)
|
||||
@@ -185,8 +193,7 @@ def texi_sections(doc, ifcond):
|
||||
body += texi_example(section.text)
|
||||
else:
|
||||
body += texi_format(section.text)
|
||||
if ifcond:
|
||||
body += '\n\n@b{If:} @code{%s}' % ", ".join(ifcond)
|
||||
body += texi_if(ifcond, suffix='')
|
||||
return body
|
||||
|
||||
|
||||
@@ -206,7 +213,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
|
||||
def write(self, output_dir):
|
||||
self._gen.write(output_dir, self._prefix + 'qapi-doc.texi')
|
||||
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
||||
doc = self.cur_doc
|
||||
self._gen.add(TYPE_FMT(type='Enum',
|
||||
name=doc.symbol,
|
||||
|
||||
@@ -143,8 +143,8 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
|
||||
QAPISchemaModularCVisitor.__init__(
|
||||
self, prefix, 'qapi-events',
|
||||
' * Schema-defined QAPI/QMP events', __doc__)
|
||||
self._enum_name = c_name(prefix + 'QAPIEvent', protect=False)
|
||||
self._event_names = []
|
||||
self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
|
||||
self._event_enum_members = []
|
||||
|
||||
def _begin_module(self, name):
|
||||
types = self._module_basename('qapi-types', name)
|
||||
@@ -170,15 +170,16 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
|
||||
|
||||
def visit_end(self):
|
||||
(genc, genh) = self._module[self._main_module]
|
||||
genh.add(gen_enum(self._enum_name, self._event_names))
|
||||
genc.add(gen_enum_lookup(self._enum_name, self._event_names))
|
||||
genh.add(gen_enum(self._event_enum_name, self._event_enum_members))
|
||||
genc.add(gen_enum_lookup(self._event_enum_name,
|
||||
self._event_enum_members))
|
||||
|
||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
||||
self._genc.add(gen_event_send(name, arg_type, boxed,
|
||||
self._enum_name))
|
||||
self._event_names.append(name)
|
||||
self._event_enum_name))
|
||||
self._event_enum_members.append(QAPISchemaMember(name, ifcond))
|
||||
|
||||
|
||||
def gen_events(schema, output_dir, prefix):
|
||||
|
||||
@@ -162,6 +162,8 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
ret = {'name': member.name, 'type': self._use_type(member.type)}
|
||||
if member.optional:
|
||||
ret['default'] = None
|
||||
if member.ifcond:
|
||||
ret = (ret, {'if': member.ifcond})
|
||||
return ret
|
||||
|
||||
def _gen_variants(self, tag_name, variants):
|
||||
@@ -169,13 +171,17 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
'variants': [self._gen_variant(v) for v in variants]}
|
||||
|
||||
def _gen_variant(self, variant):
|
||||
return {'case': variant.name, 'type': self._use_type(variant.type)}
|
||||
return ({'case': variant.name, 'type': self._use_type(variant.type)},
|
||||
{'if': variant.ifcond})
|
||||
|
||||
def visit_builtin_type(self, name, info, json_type):
|
||||
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
|
||||
|
||||
def visit_enum_type(self, name, info, ifcond, values, prefix):
|
||||
self._gen_qlit(name, 'enum', {'values': values}, ifcond)
|
||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
||||
self._gen_qlit(name, 'enum',
|
||||
{'values':
|
||||
[(m.name, {'if': m.ifcond}) for m in members]},
|
||||
ifcond)
|
||||
|
||||
def visit_array_type(self, name, info, ifcond, element_type):
|
||||
element = self._use_type(element_type)
|
||||
@@ -191,8 +197,9 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
|
||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
||||
self._gen_qlit(name, 'alternate',
|
||||
{'members': [{'type': self._use_type(m.type)}
|
||||
for m in variants.variants]}, ifcond)
|
||||
{'members': [
|
||||
({'type': self._use_type(m.type)}, {'if': m.ifcond})
|
||||
for m in variants.variants]}, ifcond)
|
||||
|
||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||
success_response, boxed, allow_oob, allow_preconfig):
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user