QAPI patches patches for 2021-08-26
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmEnhpoSHGFybWJydUBy ZWRoYXQuY29tAAoJEDhwtADrkYZT07MP/RC4fEc4Ov3ozKgUusEFDqPcZ+/yD5k4 hLHZxqMpJDqrlgQ2Pu4i53sbqlSKnZNuGkmlz3Nv8bz8CWwlfxvuMM6urGQjbOms O5MdLivka/giBNasxIUcE/kRWz2WF8/LovanS73gKP3jMkouYJarvMm0PGcOyb33 hXU/NbURmq8TyR67OK4ymtqGYwI04hGf3TSFx2qWc5dx50C4BAOyfHencG2OY1lI taG+aubLLS14eoVTFQyQOrABCv5tgZaO04DFc1XOP+L0dnuH6VEK8z6xwe6GWKmI kAeRL3R0g8UsvnkyxNRkdME/ZOuRmd5ianX0PnXl7iSWDmWpLAr8OWq7AEnlBb8w NuDia3jc85uHRXEyHy4+030MM7OvuB2cdr0mqnebn2gMBSg8E2KR+y+A/oHEUJfD FJ4und6LsGDoMHW2WQiYGN9qCGsyGpkx037BoS+HSpiVNEOSMCmGzSqQsbUGVIsK fOM2SuffrgH555kHaB5OL3l50SOO/oHXn5riyItJFuv1yGioxVAUYoerwiZPhNXd dltWQtARHnGnIW5u/BQufIAvYyT5wvLEXYZt1NzyjUQ5Eb0G8OmVkdsEh0NQcbv3 gVsj/2I+VofX/dZBWPv7/L4azKHqDPdCZ00OiKaRs44X1DBPoXToh4KBFL/HG6fL z/+5pczSpwSc =+x2Q -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-08-26' into staging QAPI patches patches for 2021-08-26 # gpg: Signature made Thu 26 Aug 2021 13:18:34 BST # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2021-08-26: qapi: make 'if' condition strings simple identifiers qapi: add 'not' condition operation qapi: Use 'if': { 'any': ... } where appropriate qapi: add 'any' condition qapi: replace if condition list with dict {'all': [...]} qapidoc: introduce QAPISchemaIfCond.docgen() qapi: introduce QAPISchemaIfCond.cgen() qapi: add QAPISchemaIfCond.is_present() qapi: wrap Sequence[str] in an object docs: update the documentation upfront about schema configuration qapi: Fix crash on redefinition with a different condition Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c83fcfaf8a
@ -826,25 +826,31 @@ Configuring the schema
|
||||
Syntax::
|
||||
|
||||
COND = STRING
|
||||
| [ STRING, ... ]
|
||||
| { 'all: [ COND, ... ] }
|
||||
| { 'any: [ COND, ... ] }
|
||||
| { 'not': COND }
|
||||
|
||||
All definitions take an optional 'if' member. 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 definition
|
||||
will then be guarded by #if STRING for each STRING in the COND list.
|
||||
string, or an object with a single member 'all', 'any' or 'not'.
|
||||
|
||||
The C code generated for the definition will then be guarded by an #if
|
||||
preprocessing directive with an operand generated from that condition:
|
||||
|
||||
* STRING will generate defined(STRING)
|
||||
* { 'all': [COND, ...] } will generate (COND && ...)
|
||||
* { 'any': [COND, ...] } will generate (COND || ...)
|
||||
* { 'not': COND } will generate !COND
|
||||
|
||||
Example: a conditional struct ::
|
||||
|
||||
{ 'struct': 'IfStruct', 'data': { 'foo': 'int' },
|
||||
'if': ['defined(CONFIG_FOO)', 'defined(HAVE_BAR)'] }
|
||||
'if': { 'all': [ 'CONFIG_FOO', 'HAVE_BAR' ] } }
|
||||
|
||||
gets its generated code guarded like this::
|
||||
|
||||
#if defined(CONFIG_FOO)
|
||||
#if defined(HAVE_BAR)
|
||||
#if defined(CONFIG_FOO) && defined(HAVE_BAR)
|
||||
... generated code ...
|
||||
#endif /* defined(HAVE_BAR) */
|
||||
#endif /* defined(CONFIG_FOO) */
|
||||
#endif /* defined(HAVE_BAR) && defined(CONFIG_FOO) */
|
||||
|
||||
Individual members of complex types, commands arguments, and
|
||||
event-specific data can also be made conditional. This requires the
|
||||
@ -855,7 +861,7 @@ member 'bar' ::
|
||||
|
||||
{ 'struct': 'IfStruct', 'data':
|
||||
{ 'foo': 'int',
|
||||
'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } }
|
||||
'bar': { 'type': 'int', 'if': 'IFCOND'} } }
|
||||
|
||||
A union's discriminator may not be conditional.
|
||||
|
||||
@ -867,7 +873,7 @@ value 'bar' ::
|
||||
|
||||
{ 'enum': 'IfEnum', 'data':
|
||||
[ 'foo',
|
||||
{ 'name' : 'bar', 'if': 'defined(IFCOND)' } ] }
|
||||
{ 'name' : 'bar', 'if': 'IFCOND' } ] }
|
||||
|
||||
Likewise, features can be conditional. This requires the longhand
|
||||
form of FEATURE_.
|
||||
@ -877,7 +883,7 @@ Example: a struct with conditional feature 'allow-negative-numbers' ::
|
||||
{ 'struct': 'TestType',
|
||||
'data': { 'number': 'int' },
|
||||
'features': [ { 'name': 'allow-negative-numbers',
|
||||
'if': 'defined(IFCOND)' } ] }
|
||||
'if': 'IFCOND' } ] }
|
||||
|
||||
Please note that you are responsible to ensure that the C code will
|
||||
compile with an arbitrary combination of conditions, since the
|
||||
|
@ -112,17 +112,19 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
def _nodes_for_ifcond(self, ifcond, with_if=True):
|
||||
"""Return list of Text, literal nodes for the ifcond
|
||||
|
||||
Return a list which gives text like ' (If: cond1, cond2, cond3)', where
|
||||
the conditions are in literal-text and the commas are not.
|
||||
Return a list which gives text like ' (If: condition)'.
|
||||
If with_if is False, we don't return the "(If: " and ")".
|
||||
"""
|
||||
condlist = intersperse([nodes.literal('', c) for c in ifcond],
|
||||
nodes.Text(', '))
|
||||
|
||||
doc = ifcond.docgen()
|
||||
if not doc:
|
||||
return []
|
||||
doc = nodes.literal('', doc)
|
||||
if not with_if:
|
||||
return condlist
|
||||
return [doc]
|
||||
|
||||
nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')]
|
||||
nodelist.extend(condlist)
|
||||
nodelist.append(doc)
|
||||
nodelist.append(nodes.Text(')'))
|
||||
return nodelist
|
||||
|
||||
@ -139,7 +141,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
term.append(nodes.literal('', member.type.doc_type()))
|
||||
if member.optional:
|
||||
term.append(nodes.Text(' (optional)'))
|
||||
if member.ifcond:
|
||||
if member.ifcond.is_present():
|
||||
term.extend(self._nodes_for_ifcond(member.ifcond))
|
||||
return term
|
||||
|
||||
@ -154,7 +156,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
nodes.literal('', variants.tag_member.name),
|
||||
nodes.Text(' is '),
|
||||
nodes.literal('', '"%s"' % variant.name)]
|
||||
if variant.ifcond:
|
||||
if variant.ifcond.is_present():
|
||||
term.extend(self._nodes_for_ifcond(variant.ifcond))
|
||||
return term
|
||||
|
||||
@ -209,7 +211,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
dlnode = nodes.definition_list()
|
||||
for section in doc.args.values():
|
||||
termtext = [nodes.literal('', section.member.name)]
|
||||
if section.member.ifcond:
|
||||
if section.member.ifcond.is_present():
|
||||
termtext.extend(self._nodes_for_ifcond(section.member.ifcond))
|
||||
# TODO drop fallbacks when undocumented members are outlawed
|
||||
if section.text:
|
||||
@ -277,7 +279,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
def _nodes_for_if_section(self, ifcond):
|
||||
"""Return list of doctree nodes for the "If" section"""
|
||||
nodelist = []
|
||||
if ifcond:
|
||||
if ifcond.is_present():
|
||||
snode = self._make_section('If')
|
||||
snode += nodes.paragraph(
|
||||
'', '', *self._nodes_for_ifcond(ifcond, with_if=False)
|
||||
|
@ -914,7 +914,7 @@
|
||||
'data': {
|
||||
'file': 'BlockStatsSpecificFile',
|
||||
'host_device': { 'type': 'BlockStatsSpecificFile',
|
||||
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
|
||||
'if': 'HAVE_HOST_BLOCK_DEVICE' },
|
||||
'nvme': 'BlockStatsSpecificNvme' } }
|
||||
|
||||
##
|
||||
@ -2796,7 +2796,7 @@
|
||||
##
|
||||
{ 'enum': 'BlockdevAioOptions',
|
||||
'data': [ 'threads', 'native',
|
||||
{ 'name': 'io_uring', 'if': 'defined(CONFIG_LINUX_IO_URING)' } ] }
|
||||
{ 'name': 'io_uring', 'if': 'CONFIG_LINUX_IO_URING' } ] }
|
||||
|
||||
##
|
||||
# @BlockdevCacheOptions:
|
||||
@ -2832,12 +2832,12 @@
|
||||
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
|
||||
'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
|
||||
'gluster',
|
||||
{'name': 'host_cdrom', 'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
|
||||
{'name': 'host_device', 'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
|
||||
{'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
|
||||
{'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
|
||||
'http', 'https', 'iscsi',
|
||||
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
|
||||
'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
|
||||
{ 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
|
||||
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
|
||||
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
|
||||
|
||||
##
|
||||
@ -2879,10 +2879,10 @@
|
||||
'*locking': 'OnOffAuto',
|
||||
'*aio': 'BlockdevAioOptions',
|
||||
'*drop-cache': {'type': 'bool',
|
||||
'if': 'defined(CONFIG_LINUX)'},
|
||||
'if': 'CONFIG_LINUX'},
|
||||
'*x-check-cache-dropped': 'bool' },
|
||||
'features': [ { 'name': 'dynamic-auto-read-only',
|
||||
'if': 'defined(CONFIG_POSIX)' } ] }
|
||||
'if': 'CONFIG_POSIX' } ] }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsNull:
|
||||
@ -3774,7 +3774,7 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsReplication:
|
||||
@ -3793,7 +3793,7 @@
|
||||
'base': 'BlockdevOptionsGenericFormat',
|
||||
'data': { 'mode': 'ReplicationMode',
|
||||
'*top-id': 'str' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @NFSTransport:
|
||||
@ -4108,9 +4108,9 @@
|
||||
'ftps': 'BlockdevOptionsCurlFtps',
|
||||
'gluster': 'BlockdevOptionsGluster',
|
||||
'host_cdrom': { 'type': 'BlockdevOptionsFile',
|
||||
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
|
||||
'if': 'HAVE_HOST_BLOCK_DEVICE' },
|
||||
'host_device': { 'type': 'BlockdevOptionsFile',
|
||||
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' },
|
||||
'if': 'HAVE_HOST_BLOCK_DEVICE' },
|
||||
'http': 'BlockdevOptionsCurlHttp',
|
||||
'https': 'BlockdevOptionsCurlHttps',
|
||||
'iscsi': 'BlockdevOptionsIscsi',
|
||||
@ -4129,7 +4129,7 @@
|
||||
'raw': 'BlockdevOptionsRaw',
|
||||
'rbd': 'BlockdevOptionsRbd',
|
||||
'replication': { 'type': 'BlockdevOptionsReplication',
|
||||
'if': 'defined(CONFIG_REPLICATION)' },
|
||||
'if': 'CONFIG_REPLICATION' },
|
||||
'ssh': 'BlockdevOptionsSsh',
|
||||
'throttle': 'BlockdevOptionsThrottle',
|
||||
'vdi': 'BlockdevOptionsGenericFormat',
|
||||
@ -4307,8 +4307,8 @@
|
||||
# @size: Size of the virtual disk in bytes
|
||||
# @preallocation: Preallocation mode for the new image (default: off;
|
||||
# allowed values: off,
|
||||
# falloc (if defined CONFIG_POSIX_FALLOCATE),
|
||||
# full (if defined CONFIG_POSIX))
|
||||
# falloc (if CONFIG_POSIX_FALLOCATE),
|
||||
# full (if CONFIG_POSIX))
|
||||
# @nocow: Turn off copy-on-write (valid only on btrfs; default: off)
|
||||
# @extent-size-hint: Extent size hint to add to the image file; 0 for not
|
||||
# adding an extent size hint (default: 1 MB, since 5.1)
|
||||
@ -4331,8 +4331,8 @@
|
||||
# @size: Size of the virtual disk in bytes
|
||||
# @preallocation: Preallocation mode for the new image (default: off;
|
||||
# allowed values: off,
|
||||
# falloc (if defined CONFIG_GLUSTERFS_FALLOCATE),
|
||||
# full (if defined CONFIG_GLUSTERFS_ZEROFILL))
|
||||
# falloc (if CONFIG_GLUSTERFS_FALLOCATE),
|
||||
# full (if CONFIG_GLUSTERFS_ZEROFILL))
|
||||
#
|
||||
# Since: 2.12
|
||||
##
|
||||
@ -4432,7 +4432,7 @@
|
||||
# Since: 5.1
|
||||
##
|
||||
{ 'enum': 'Qcow2CompressionType',
|
||||
'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] }
|
||||
'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
|
||||
|
||||
##
|
||||
# @BlockdevCreateOptionsQcow2:
|
||||
|
@ -168,7 +168,7 @@
|
||||
'data': { 'mountpoint': 'str',
|
||||
'*growable': 'bool',
|
||||
'*allow-other': 'FuseExportAllowOther' },
|
||||
'if': 'defined(CONFIG_FUSE)' }
|
||||
'if': 'CONFIG_FUSE' }
|
||||
|
||||
##
|
||||
# @NbdServerAddOptions:
|
||||
@ -278,7 +278,7 @@
|
||||
##
|
||||
{ 'enum': 'BlockExportType',
|
||||
'data': [ 'nbd', 'vhost-user-blk',
|
||||
{ 'name': 'fuse', 'if': 'defined(CONFIG_FUSE)' } ] }
|
||||
{ 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] }
|
||||
|
||||
##
|
||||
# @BlockExportOptions:
|
||||
@ -321,7 +321,7 @@
|
||||
'nbd': 'BlockExportOptionsNbd',
|
||||
'vhost-user-blk': 'BlockExportOptionsVhostUserBlk',
|
||||
'fuse': { 'type': 'BlockExportOptionsFuse',
|
||||
'if': 'defined(CONFIG_FUSE)' }
|
||||
'if': 'CONFIG_FUSE' }
|
||||
} }
|
||||
|
||||
##
|
||||
|
@ -342,7 +342,7 @@
|
||||
{ 'struct': 'ChardevSpiceChannel',
|
||||
'data': { 'type': 'str' },
|
||||
'base': 'ChardevCommon',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @ChardevSpicePort:
|
||||
@ -356,7 +356,7 @@
|
||||
{ 'struct': 'ChardevSpicePort',
|
||||
'data': { 'fqdn': 'str' },
|
||||
'base': 'ChardevCommon',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @ChardevVC:
|
||||
@ -405,7 +405,7 @@
|
||||
'data': { '*mouse': 'bool',
|
||||
'*clipboard': 'bool' },
|
||||
'base': 'ChardevCommon',
|
||||
'if': 'defined(CONFIG_SPICE_PROTOCOL)' }
|
||||
'if': 'CONFIG_SPICE_PROTOCOL' }
|
||||
|
||||
##
|
||||
# @ChardevBackend:
|
||||
@ -431,11 +431,11 @@
|
||||
'stdio': 'ChardevStdio',
|
||||
'console': 'ChardevCommon',
|
||||
'spicevmc': { 'type': 'ChardevSpiceChannel',
|
||||
'if': 'defined(CONFIG_SPICE)' },
|
||||
'if': 'CONFIG_SPICE' },
|
||||
'spiceport': { 'type': 'ChardevSpicePort',
|
||||
'if': 'defined(CONFIG_SPICE)' },
|
||||
'if': 'CONFIG_SPICE' },
|
||||
'qemu-vdagent': { 'type': 'ChardevQemuVDAgent',
|
||||
'if': 'defined(CONFIG_SPICE_PROTOCOL)' },
|
||||
'if': 'CONFIG_SPICE_PROTOCOL' },
|
||||
'vc': 'ChardevVC',
|
||||
'ringbuf': 'ChardevRingbuf',
|
||||
# next one is just for compatibility
|
||||
|
@ -89,7 +89,7 @@
|
||||
##
|
||||
{ 'struct': 'CpuModelBaselineInfo',
|
||||
'data': { 'model': 'CpuModelInfo' },
|
||||
'if': 'defined(TARGET_S390X)' }
|
||||
'if': 'TARGET_S390X' }
|
||||
|
||||
##
|
||||
# @CpuModelCompareInfo:
|
||||
@ -112,7 +112,7 @@
|
||||
{ 'struct': 'CpuModelCompareInfo',
|
||||
'data': { 'result': 'CpuModelCompareResult',
|
||||
'responsible-properties': ['str'] },
|
||||
'if': 'defined(TARGET_S390X)' }
|
||||
'if': 'TARGET_S390X' }
|
||||
|
||||
##
|
||||
# @query-cpu-model-comparison:
|
||||
@ -156,7 +156,7 @@
|
||||
{ 'command': 'query-cpu-model-comparison',
|
||||
'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
|
||||
'returns': 'CpuModelCompareInfo',
|
||||
'if': 'defined(TARGET_S390X)' }
|
||||
'if': 'TARGET_S390X' }
|
||||
|
||||
##
|
||||
# @query-cpu-model-baseline:
|
||||
@ -200,7 +200,7 @@
|
||||
'data': { 'modela': 'CpuModelInfo',
|
||||
'modelb': 'CpuModelInfo' },
|
||||
'returns': 'CpuModelBaselineInfo',
|
||||
'if': 'defined(TARGET_S390X)' }
|
||||
'if': 'TARGET_S390X' }
|
||||
|
||||
##
|
||||
# @CpuModelExpansionInfo:
|
||||
@ -213,7 +213,9 @@
|
||||
##
|
||||
{ 'struct': 'CpuModelExpansionInfo',
|
||||
'data': { 'model': 'CpuModelInfo' },
|
||||
'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
|
||||
'if': { 'any': [ 'TARGET_S390X',
|
||||
'TARGET_I386',
|
||||
'TARGET_ARM' ] } }
|
||||
|
||||
##
|
||||
# @query-cpu-model-expansion:
|
||||
@ -252,7 +254,9 @@
|
||||
'data': { 'type': 'CpuModelExpansionType',
|
||||
'model': 'CpuModelInfo' },
|
||||
'returns': 'CpuModelExpansionInfo',
|
||||
'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
|
||||
'if': { 'any': [ 'TARGET_S390X',
|
||||
'TARGET_I386',
|
||||
'TARGET_ARM' ] } }
|
||||
|
||||
##
|
||||
# @CpuDefinitionInfo:
|
||||
@ -316,7 +320,11 @@
|
||||
'typename': 'str',
|
||||
'*alias-of' : 'str',
|
||||
'deprecated' : 'bool' },
|
||||
'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
|
||||
'if': { 'any': [ 'TARGET_PPC',
|
||||
'TARGET_ARM',
|
||||
'TARGET_I386',
|
||||
'TARGET_S390X',
|
||||
'TARGET_MIPS' ] } }
|
||||
|
||||
##
|
||||
# @query-cpu-definitions:
|
||||
@ -328,4 +336,8 @@
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
|
||||
'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
|
||||
'if': { 'any': [ 'TARGET_PPC',
|
||||
'TARGET_ARM',
|
||||
'TARGET_I386',
|
||||
'TARGET_S390X',
|
||||
'TARGET_MIPS' ] } }
|
||||
|
@ -533,7 +533,7 @@
|
||||
##
|
||||
{ 'enum': 'MultiFDCompression',
|
||||
'data': [ 'none', 'zlib',
|
||||
{ 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] }
|
||||
{ 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
|
||||
|
||||
##
|
||||
# @BitmapMigrationBitmapAliasTransform:
|
||||
@ -1562,7 +1562,7 @@
|
||||
##
|
||||
{ 'command': 'xen-set-replication',
|
||||
'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @ReplicationStatus:
|
||||
@ -1578,7 +1578,7 @@
|
||||
##
|
||||
{ 'struct': 'ReplicationStatus',
|
||||
'data': { 'error': 'bool', '*desc': 'str' },
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @query-xen-replication-status:
|
||||
@ -1596,7 +1596,7 @@
|
||||
##
|
||||
{ 'command': 'query-xen-replication-status',
|
||||
'returns': 'ReplicationStatus',
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @xen-colo-do-checkpoint:
|
||||
@ -1613,7 +1613,7 @@
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'command': 'xen-colo-do-checkpoint',
|
||||
'if': 'defined(CONFIG_REPLICATION)' }
|
||||
'if': 'CONFIG_REPLICATION' }
|
||||
|
||||
##
|
||||
# @COLOStatus:
|
||||
|
@ -23,7 +23,17 @@
|
||||
##
|
||||
{ 'event': 'RTC_CHANGE',
|
||||
'data': { 'offset': 'int' },
|
||||
'if': 'defined(TARGET_ALPHA) || defined(TARGET_ARM) || defined(TARGET_HPPA) || defined(TARGET_I386) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) || defined(TARGET_PPC) || defined(TARGET_PPC64) || defined(TARGET_S390X) || defined(TARGET_SH4) || defined(TARGET_SPARC)' }
|
||||
'if': { 'any': [ 'TARGET_ALPHA',
|
||||
'TARGET_ARM',
|
||||
'TARGET_HPPA',
|
||||
'TARGET_I386',
|
||||
'TARGET_MIPS',
|
||||
'TARGET_MIPS64',
|
||||
'TARGET_PPC',
|
||||
'TARGET_PPC64',
|
||||
'TARGET_S390X',
|
||||
'TARGET_SH4',
|
||||
'TARGET_SPARC' ] } }
|
||||
|
||||
##
|
||||
# @rtc-reset-reinjection:
|
||||
@ -42,7 +52,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'rtc-reset-reinjection',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
|
||||
##
|
||||
@ -69,7 +79,7 @@
|
||||
{ 'enum': 'SevState',
|
||||
'data': ['uninit', 'launch-update', 'launch-secret', 'running',
|
||||
'send-update', 'receive-update' ],
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @SevInfo:
|
||||
@ -101,7 +111,7 @@
|
||||
'state' : 'SevState',
|
||||
'handle' : 'uint32'
|
||||
},
|
||||
'if': 'defined(TARGET_I386)'
|
||||
'if': 'TARGET_I386'
|
||||
}
|
||||
|
||||
##
|
||||
@ -122,7 +132,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-sev', 'returns': 'SevInfo',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
|
||||
##
|
||||
@ -136,7 +146,7 @@
|
||||
#
|
||||
##
|
||||
{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'},
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @query-sev-launch-measure:
|
||||
@ -154,7 +164,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
|
||||
##
|
||||
@ -179,7 +189,7 @@
|
||||
'cert-chain': 'str',
|
||||
'cbitpos': 'int',
|
||||
'reduced-phys-bits': 'int'},
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @query-sev-capabilities:
|
||||
@ -199,7 +209,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @sev-inject-launch-secret:
|
||||
@ -217,7 +227,7 @@
|
||||
##
|
||||
{ 'command': 'sev-inject-launch-secret',
|
||||
'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' },
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @dump-skeys:
|
||||
@ -239,7 +249,7 @@
|
||||
##
|
||||
{ 'command': 'dump-skeys',
|
||||
'data': { 'filename': 'str' },
|
||||
'if': 'defined(TARGET_S390X)' }
|
||||
'if': 'TARGET_S390X' }
|
||||
|
||||
##
|
||||
# @GICCapability:
|
||||
@ -264,7 +274,7 @@
|
||||
'data': { 'version': 'int',
|
||||
'emulated': 'bool',
|
||||
'kernel': 'bool' },
|
||||
'if': 'defined(TARGET_ARM)' }
|
||||
'if': 'TARGET_ARM' }
|
||||
|
||||
##
|
||||
# @query-gic-capabilities:
|
||||
@ -284,7 +294,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
|
||||
'if': 'defined(TARGET_ARM)' }
|
||||
'if': 'TARGET_ARM' }
|
||||
|
||||
|
||||
##
|
||||
@ -300,7 +310,7 @@
|
||||
##
|
||||
{ 'struct': 'SevAttestationReport',
|
||||
'data': { 'data': 'str'},
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
||||
##
|
||||
# @query-sev-attestation-report:
|
||||
@ -322,4 +332,4 @@
|
||||
##
|
||||
{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
|
||||
'returns': 'SevAttestationReport',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
'if': 'TARGET_I386' }
|
||||
|
@ -618,7 +618,7 @@
|
||||
'data': { '*align': 'size',
|
||||
'*discard-data': 'bool',
|
||||
'mem-path': 'str',
|
||||
'*pmem': { 'type': 'bool', 'if': 'defined(CONFIG_LIBPMEM)' },
|
||||
'*pmem': { 'type': 'bool', 'if': 'CONFIG_LIBPMEM' },
|
||||
'*readonly': 'bool' } }
|
||||
|
||||
##
|
||||
@ -782,7 +782,7 @@
|
||||
'cryptodev-backend',
|
||||
'cryptodev-backend-builtin',
|
||||
{ 'name': 'cryptodev-vhost-user',
|
||||
'if': 'defined(CONFIG_VHOST_CRYPTO)' },
|
||||
'if': 'CONFIG_VHOST_CRYPTO' },
|
||||
'dbus-vmstate',
|
||||
'filter-buffer',
|
||||
'filter-dump',
|
||||
@ -795,7 +795,7 @@
|
||||
'iothread',
|
||||
'memory-backend-file',
|
||||
{ 'name': 'memory-backend-memfd',
|
||||
'if': 'defined(CONFIG_LINUX)' },
|
||||
'if': 'CONFIG_LINUX' },
|
||||
'memory-backend-ram',
|
||||
'pef-guest',
|
||||
'pr-manager-helper',
|
||||
@ -840,7 +840,7 @@
|
||||
'cryptodev-backend': 'CryptodevBackendProperties',
|
||||
'cryptodev-backend-builtin': 'CryptodevBackendProperties',
|
||||
'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties',
|
||||
'if': 'defined(CONFIG_VHOST_CRYPTO)' },
|
||||
'if': 'CONFIG_VHOST_CRYPTO' },
|
||||
'dbus-vmstate': 'DBusVMStateProperties',
|
||||
'filter-buffer': 'FilterBufferProperties',
|
||||
'filter-dump': 'FilterDumpProperties',
|
||||
@ -853,7 +853,7 @@
|
||||
'iothread': 'IothreadProperties',
|
||||
'memory-backend-file': 'MemoryBackendFileProperties',
|
||||
'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties',
|
||||
'if': 'defined(CONFIG_LINUX)' },
|
||||
'if': 'CONFIG_LINUX' },
|
||||
'memory-backend-ram': 'MemoryBackendProperties',
|
||||
'pr-manager-helper': 'PrManagerHelperProperties',
|
||||
'qtest': 'QtestProperties',
|
||||
|
@ -69,7 +69,7 @@
|
||||
'*ipv4': 'bool',
|
||||
'*ipv6': 'bool',
|
||||
'*keep-alive': 'bool',
|
||||
'*mptcp': { 'type': 'bool', 'if': 'defined(IPPROTO_MPTCP)' } } }
|
||||
'*mptcp': { 'type': 'bool', 'if': 'IPPROTO_MPTCP' } } }
|
||||
|
||||
##
|
||||
# @UnixSocketAddress:
|
||||
@ -89,8 +89,8 @@
|
||||
{ 'struct': 'UnixSocketAddress',
|
||||
'data': {
|
||||
'path': 'str',
|
||||
'*abstract': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' },
|
||||
'*tight': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' } } }
|
||||
'*abstract': { 'type': 'bool', 'if': 'CONFIG_LINUX' },
|
||||
'*tight': { 'type': 'bool', 'if': 'CONFIG_LINUX' } } }
|
||||
|
||||
##
|
||||
# @VsockSocketAddress:
|
||||
|
@ -18,7 +18,7 @@
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ],
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @query-tpm-models:
|
||||
@ -36,7 +36,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm-models', 'returns': ['TpmModel'],
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @TpmType:
|
||||
@ -50,7 +50,7 @@
|
||||
# Since: 1.5
|
||||
##
|
||||
{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ],
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @query-tpm-types:
|
||||
@ -68,7 +68,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm-types', 'returns': ['TpmType'],
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @TPMPassthroughOptions:
|
||||
@ -85,7 +85,7 @@
|
||||
{ 'struct': 'TPMPassthroughOptions',
|
||||
'data': { '*path': 'str',
|
||||
'*cancel-path': 'str' },
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @TPMEmulatorOptions:
|
||||
@ -97,7 +97,7 @@
|
||||
# Since: 2.11
|
||||
##
|
||||
{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @TpmTypeOptions:
|
||||
@ -112,7 +112,7 @@
|
||||
{ 'union': 'TpmTypeOptions',
|
||||
'data': { 'passthrough' : 'TPMPassthroughOptions',
|
||||
'emulator': 'TPMEmulatorOptions' },
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @TPMInfo:
|
||||
@ -131,7 +131,7 @@
|
||||
'data': {'id': 'str',
|
||||
'model': 'TpmModel',
|
||||
'options': 'TpmTypeOptions' },
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
||||
##
|
||||
# @query-tpm:
|
||||
@ -162,4 +162,4 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-tpm', 'returns': ['TPMInfo'],
|
||||
'if': 'defined(CONFIG_TPM)' }
|
||||
'if': 'CONFIG_TPM' }
|
||||
|
66
qapi/ui.json
66
qapi/ui.json
@ -123,7 +123,7 @@
|
||||
'data': { 'host': 'str',
|
||||
'port': 'str',
|
||||
'family': 'NetworkAddressFamily' },
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SpiceServerInfo:
|
||||
@ -137,7 +137,7 @@
|
||||
{ 'struct': 'SpiceServerInfo',
|
||||
'base': 'SpiceBasicInfo',
|
||||
'data': { '*auth': 'str' },
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SpiceChannel:
|
||||
@ -163,7 +163,7 @@
|
||||
'base': 'SpiceBasicInfo',
|
||||
'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
|
||||
'tls': 'bool'},
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SpiceQueryMouseMode:
|
||||
@ -183,7 +183,7 @@
|
||||
##
|
||||
{ 'enum': 'SpiceQueryMouseMode',
|
||||
'data': [ 'client', 'server', 'unknown' ],
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SpiceInfo:
|
||||
@ -222,7 +222,7 @@
|
||||
'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
|
||||
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
|
||||
'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']},
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @query-spice:
|
||||
@ -268,7 +268,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-spice', 'returns': 'SpiceInfo',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SPICE_CONNECTED:
|
||||
@ -294,7 +294,7 @@
|
||||
{ 'event': 'SPICE_CONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' },
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SPICE_INITIALIZED:
|
||||
@ -323,7 +323,7 @@
|
||||
{ 'event': 'SPICE_INITIALIZED',
|
||||
'data': { 'server': 'SpiceServerInfo',
|
||||
'client': 'SpiceChannel' },
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SPICE_DISCONNECTED:
|
||||
@ -349,7 +349,7 @@
|
||||
{ 'event': 'SPICE_DISCONNECTED',
|
||||
'data': { 'server': 'SpiceBasicInfo',
|
||||
'client': 'SpiceBasicInfo' },
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# @SPICE_MIGRATE_COMPLETED:
|
||||
@ -365,7 +365,7 @@
|
||||
#
|
||||
##
|
||||
{ 'event': 'SPICE_MIGRATE_COMPLETED',
|
||||
'if': 'defined(CONFIG_SPICE)' }
|
||||
'if': 'CONFIG_SPICE' }
|
||||
|
||||
##
|
||||
# == VNC
|
||||
@ -393,7 +393,7 @@
|
||||
'service': 'str',
|
||||
'family': 'NetworkAddressFamily',
|
||||
'websocket': 'bool' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncServerInfo:
|
||||
@ -408,7 +408,7 @@
|
||||
{ 'struct': 'VncServerInfo',
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { '*auth': 'str' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncClientInfo:
|
||||
@ -426,7 +426,7 @@
|
||||
{ 'struct': 'VncClientInfo',
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncInfo:
|
||||
@ -469,7 +469,7 @@
|
||||
'data': {'enabled': 'bool', '*host': 'str',
|
||||
'*family': 'NetworkAddressFamily',
|
||||
'*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']},
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncPrimaryAuth:
|
||||
@ -481,7 +481,7 @@
|
||||
{ 'enum': 'VncPrimaryAuth',
|
||||
'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
|
||||
'tls', 'vencrypt', 'sasl' ],
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncVencryptSubAuth:
|
||||
@ -496,7 +496,7 @@
|
||||
'tls-vnc', 'x509-vnc',
|
||||
'tls-plain', 'x509-plain',
|
||||
'tls-sasl', 'x509-sasl' ],
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncServerInfo2:
|
||||
@ -514,7 +514,7 @@
|
||||
'base': 'VncBasicInfo',
|
||||
'data': { 'auth' : 'VncPrimaryAuth',
|
||||
'*vencrypt' : 'VncVencryptSubAuth' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VncInfo2:
|
||||
@ -547,7 +547,7 @@
|
||||
'auth' : 'VncPrimaryAuth',
|
||||
'*vencrypt' : 'VncVencryptSubAuth',
|
||||
'*display' : 'str' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @query-vnc:
|
||||
@ -579,7 +579,7 @@
|
||||
#
|
||||
##
|
||||
{ 'command': 'query-vnc', 'returns': 'VncInfo',
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
##
|
||||
# @query-vnc-servers:
|
||||
#
|
||||
@ -590,7 +590,7 @@
|
||||
# Since: 2.3
|
||||
##
|
||||
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @change-vnc-password:
|
||||
@ -606,7 +606,7 @@
|
||||
##
|
||||
{ 'command': 'change-vnc-password',
|
||||
'data': { 'password': 'str' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VNC_CONNECTED:
|
||||
@ -636,7 +636,7 @@
|
||||
{ 'event': 'VNC_CONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncBasicInfo' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VNC_INITIALIZED:
|
||||
@ -664,7 +664,7 @@
|
||||
{ 'event': 'VNC_INITIALIZED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# @VNC_DISCONNECTED:
|
||||
@ -691,7 +691,7 @@
|
||||
{ 'event': 'VNC_DISCONNECTED',
|
||||
'data': { 'server': 'VncServerInfo',
|
||||
'client': 'VncClientInfo' },
|
||||
'if': 'defined(CONFIG_VNC)' }
|
||||
'if': 'CONFIG_VNC' }
|
||||
|
||||
##
|
||||
# = Input
|
||||
@ -1133,13 +1133,13 @@
|
||||
'data' : [
|
||||
{ 'name': 'default' },
|
||||
{ 'name': 'none' },
|
||||
{ 'name': 'gtk', 'if': 'defined(CONFIG_GTK)' },
|
||||
{ 'name': 'sdl', 'if': 'defined(CONFIG_SDL)' },
|
||||
{ 'name': 'gtk', 'if': 'CONFIG_GTK' },
|
||||
{ 'name': 'sdl', 'if': 'CONFIG_SDL' },
|
||||
{ 'name': 'egl-headless',
|
||||
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' },
|
||||
{ 'name': 'curses', 'if': 'defined(CONFIG_CURSES)' },
|
||||
{ 'name': 'cocoa', 'if': 'defined(CONFIG_COCOA)' },
|
||||
{ 'name': 'spice-app', 'if': 'defined(CONFIG_SPICE)'} ] }
|
||||
'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } },
|
||||
{ 'name': 'curses', 'if': 'CONFIG_CURSES' },
|
||||
{ 'name': 'cocoa', 'if': 'CONFIG_COCOA' },
|
||||
{ 'name': 'spice-app', 'if': 'CONFIG_SPICE'} ] }
|
||||
|
||||
##
|
||||
# @DisplayOptions:
|
||||
@ -1164,10 +1164,10 @@
|
||||
'*gl' : 'DisplayGLMode' },
|
||||
'discriminator' : 'type',
|
||||
'data' : {
|
||||
'gtk': { 'type': 'DisplayGTK', 'if': 'defined(CONFIG_GTK)' },
|
||||
'curses': { 'type': 'DisplayCurses', 'if': 'defined(CONFIG_CURSES)' },
|
||||
'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' },
|
||||
'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' },
|
||||
'egl-headless': { 'type': 'DisplayEGLHeadless',
|
||||
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' }
|
||||
'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1380,7 +1380,7 @@
|
||||
'data': {
|
||||
'keys': ['str']
|
||||
},
|
||||
'if': 'defined(CONFIG_POSIX)' }
|
||||
'if': 'CONFIG_POSIX' }
|
||||
|
||||
|
||||
##
|
||||
@ -1398,7 +1398,7 @@
|
||||
{ 'command': 'guest-ssh-get-authorized-keys',
|
||||
'data': { 'username': 'str' },
|
||||
'returns': 'GuestAuthorizedKeys',
|
||||
'if': 'defined(CONFIG_POSIX)' }
|
||||
'if': 'CONFIG_POSIX' }
|
||||
|
||||
##
|
||||
# @guest-ssh-add-authorized-keys:
|
||||
@ -1416,7 +1416,7 @@
|
||||
##
|
||||
{ 'command': 'guest-ssh-add-authorized-keys',
|
||||
'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' },
|
||||
'if': 'defined(CONFIG_POSIX)' }
|
||||
'if': 'CONFIG_POSIX' }
|
||||
|
||||
##
|
||||
# @guest-ssh-remove-authorized-keys:
|
||||
@ -1434,4 +1434,4 @@
|
||||
##
|
||||
{ 'command': 'guest-ssh-remove-authorized-keys',
|
||||
'data': { 'username': 'str', 'keys': ['str'] },
|
||||
'if': 'defined(CONFIG_POSIX)' }
|
||||
'if': 'CONFIG_POSIX' }
|
||||
|
@ -17,7 +17,6 @@ from typing import (
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Set,
|
||||
)
|
||||
|
||||
@ -31,6 +30,7 @@ from .gen import (
|
||||
from .schema import (
|
||||
QAPISchema,
|
||||
QAPISchemaFeature,
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaObjectType,
|
||||
QAPISchemaType,
|
||||
)
|
||||
@ -301,7 +301,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
|
||||
def visit_command(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
arg_type: Optional[QAPISchemaObjectType],
|
||||
ret_type: Optional[QAPISchemaType],
|
||||
|
@ -12,7 +12,13 @@
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import re
|
||||
from typing import Match, Optional, Sequence
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
Match,
|
||||
Optional,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
||||
#: Magic string that gets removed along with all space to its right.
|
||||
@ -194,22 +200,49 @@ def guardend(name: str) -> str:
|
||||
name=c_fname(name).upper())
|
||||
|
||||
|
||||
def gen_if(ifcond: Sequence[str]) -> str:
|
||||
ret = ''
|
||||
for ifc in ifcond:
|
||||
ret += mcgen('''
|
||||
def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
|
||||
if not ifcond:
|
||||
return ''
|
||||
if isinstance(ifcond, str):
|
||||
return 'defined(' + ifcond + ')'
|
||||
|
||||
oper, operands = next(iter(ifcond.items()))
|
||||
if oper == 'not':
|
||||
return '!' + cgen_ifcond(operands)
|
||||
oper = {'all': '&&', 'any': '||'}[oper]
|
||||
operands = [cgen_ifcond(o) for o in operands]
|
||||
return '(' + (') ' + oper + ' (').join(operands) + ')'
|
||||
|
||||
|
||||
def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
|
||||
# TODO Doc generated for conditions needs polish
|
||||
if not ifcond:
|
||||
return ''
|
||||
if isinstance(ifcond, str):
|
||||
return ifcond
|
||||
|
||||
oper, operands = next(iter(ifcond.items()))
|
||||
if oper == 'not':
|
||||
return '!' + docgen_ifcond(operands)
|
||||
oper = {'all': ' and ', 'any': ' or '}[oper]
|
||||
operands = [docgen_ifcond(o) for o in operands]
|
||||
return '(' + oper.join(operands) + ')'
|
||||
|
||||
|
||||
def gen_if(cond: str) -> str:
|
||||
if not cond:
|
||||
return ''
|
||||
return mcgen('''
|
||||
#if %(cond)s
|
||||
''', cond=ifc)
|
||||
return ret
|
||||
''', cond=cond)
|
||||
|
||||
|
||||
def gen_endif(ifcond: Sequence[str]) -> str:
|
||||
ret = ''
|
||||
for ifc in reversed(ifcond):
|
||||
ret += mcgen('''
|
||||
def gen_endif(cond: str) -> str:
|
||||
if not cond:
|
||||
return ''
|
||||
return mcgen('''
|
||||
#endif /* %(cond)s */
|
||||
''', cond=ifc)
|
||||
return ret
|
||||
''', cond=cond)
|
||||
|
||||
|
||||
def must_match(pattern: str, string: str) -> Match[str]:
|
||||
|
@ -12,7 +12,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
|
||||
See the COPYING file in the top-level directory.
|
||||
"""
|
||||
|
||||
from typing import List, Optional, Sequence
|
||||
from typing import List, Optional
|
||||
|
||||
from .common import c_enum_const, c_name, mcgen
|
||||
from .gen import QAPISchemaModularCVisitor, build_params, ifcontext
|
||||
@ -20,6 +20,7 @@ from .schema import (
|
||||
QAPISchema,
|
||||
QAPISchemaEnumMember,
|
||||
QAPISchemaFeature,
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaObjectType,
|
||||
)
|
||||
from .source import QAPISourceInfo
|
||||
@ -227,7 +228,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict);
|
||||
def visit_event(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
arg_type: Optional[QAPISchemaObjectType],
|
||||
boxed: bool) -> None:
|
||||
|
@ -259,14 +259,9 @@ def check_flags(expr: _JSONObject, info: QAPISourceInfo) -> None:
|
||||
|
||||
def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
||||
"""
|
||||
Normalize and validate the ``if`` member of an object.
|
||||
Validate the ``if`` member of an object.
|
||||
|
||||
The ``if`` member may be either a ``str`` or a ``List[str]``.
|
||||
A ``str`` value will be normalized to ``List[str]``.
|
||||
|
||||
:forms:
|
||||
:sugared: ``Union[str, List[str]]``
|
||||
:canonical: ``List[str]``
|
||||
The ``if`` member may be either a ``str`` or a dict.
|
||||
|
||||
:param expr: The expression containing the ``if`` member to validate.
|
||||
:param info: QAPI schema source file information.
|
||||
@ -275,31 +270,49 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
||||
:raise QAPISemError:
|
||||
When the "if" member fails validation, or when there are no
|
||||
non-empty conditions.
|
||||
:return: None, ``expr`` is normalized in-place as needed.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def _check_if(cond: Union[str, object]) -> None:
|
||||
if isinstance(cond, str):
|
||||
if not re.match(r'^[A-Z][A-Z0-9_]*$', cond):
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition '%s' of %s is not a valid identifier"
|
||||
% (cond, source))
|
||||
return
|
||||
|
||||
if not isinstance(cond, dict):
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition of %s must be a string or an object" % source)
|
||||
if len(cond) != 1:
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition dict of %s must have one key: "
|
||||
"'all', 'any' or 'not'" % source)
|
||||
check_keys(cond, info, "'if' condition", [],
|
||||
["all", "any", "not"])
|
||||
|
||||
oper, operands = next(iter(cond.items()))
|
||||
if not operands:
|
||||
raise QAPISemError(
|
||||
info, "'if' condition [] of %s is useless" % source)
|
||||
|
||||
if oper == "not":
|
||||
_check_if(operands)
|
||||
return
|
||||
if oper in ("all", "any") and not isinstance(operands, list):
|
||||
raise QAPISemError(
|
||||
info, "'%s' condition of %s must be an array" % (oper, source))
|
||||
for operand in operands:
|
||||
_check_if(operand)
|
||||
|
||||
ifcond = expr.get('if')
|
||||
if ifcond is None:
|
||||
return
|
||||
|
||||
if isinstance(ifcond, list):
|
||||
if not ifcond:
|
||||
raise QAPISemError(
|
||||
info, "'if' condition [] of %s is useless" % source)
|
||||
else:
|
||||
# Normalize to a list
|
||||
ifcond = expr['if'] = [ifcond]
|
||||
|
||||
for elt in ifcond:
|
||||
if not isinstance(elt, str):
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition of %s must be a string or a list of strings"
|
||||
% source)
|
||||
if not elt.strip():
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition '%s' of %s makes no sense"
|
||||
% (elt, source))
|
||||
_check_if(ifcond)
|
||||
|
||||
|
||||
def normalize_members(members: object) -> None:
|
||||
|
@ -18,7 +18,6 @@ from typing import (
|
||||
Dict,
|
||||
Iterator,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
)
|
||||
|
||||
@ -32,6 +31,7 @@ from .common import (
|
||||
mcgen,
|
||||
)
|
||||
from .schema import (
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaModule,
|
||||
QAPISchemaObjectType,
|
||||
QAPISchemaVisitor,
|
||||
@ -85,7 +85,7 @@ class QAPIGen:
|
||||
fp.write(text)
|
||||
|
||||
|
||||
def _wrap_ifcond(ifcond: Sequence[str], before: str, after: str) -> str:
|
||||
def _wrap_ifcond(ifcond: QAPISchemaIfCond, before: str, after: str) -> str:
|
||||
if before == after:
|
||||
return after # suppress empty #if ... #endif
|
||||
|
||||
@ -95,9 +95,9 @@ def _wrap_ifcond(ifcond: Sequence[str], before: str, after: str) -> str:
|
||||
if added[0] == '\n':
|
||||
out += '\n'
|
||||
added = added[1:]
|
||||
out += gen_if(ifcond)
|
||||
out += gen_if(ifcond.cgen())
|
||||
out += added
|
||||
out += gen_endif(ifcond)
|
||||
out += gen_endif(ifcond.cgen())
|
||||
return out
|
||||
|
||||
|
||||
@ -127,9 +127,9 @@ def build_params(arg_type: Optional[QAPISchemaObjectType],
|
||||
class QAPIGenCCode(QAPIGen):
|
||||
def __init__(self, fname: str):
|
||||
super().__init__(fname)
|
||||
self._start_if: Optional[Tuple[Sequence[str], str, str]] = None
|
||||
self._start_if: Optional[Tuple[QAPISchemaIfCond, str, str]] = None
|
||||
|
||||
def start_if(self, ifcond: Sequence[str]) -> None:
|
||||
def start_if(self, ifcond: QAPISchemaIfCond) -> None:
|
||||
assert self._start_if is None
|
||||
self._start_if = (ifcond, self._body, self._preamble)
|
||||
|
||||
@ -187,7 +187,7 @@ class QAPIGenH(QAPIGenC):
|
||||
|
||||
|
||||
@contextmanager
|
||||
def ifcontext(ifcond: Sequence[str], *args: QAPIGenCCode) -> Iterator[None]:
|
||||
def ifcontext(ifcond: QAPISchemaIfCond, *args: QAPIGenCCode) -> Iterator[None]:
|
||||
"""
|
||||
A with-statement context manager that wraps with `start_if()` / `end_if()`.
|
||||
|
||||
|
@ -15,11 +15,9 @@ from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
Generic,
|
||||
Iterable,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
@ -38,6 +36,7 @@ from .schema import (
|
||||
QAPISchemaEntity,
|
||||
QAPISchemaEnumMember,
|
||||
QAPISchemaFeature,
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaObjectType,
|
||||
QAPISchemaObjectTypeMember,
|
||||
QAPISchemaType,
|
||||
@ -91,11 +90,11 @@ class Annotated(Generic[_ValueT]):
|
||||
"""
|
||||
# TODO: Remove after Python 3.7 adds @dataclass:
|
||||
# pylint: disable=too-few-public-methods
|
||||
def __init__(self, value: _ValueT, ifcond: Iterable[str],
|
||||
def __init__(self, value: _ValueT, ifcond: QAPISchemaIfCond,
|
||||
comment: Optional[str] = None):
|
||||
self.value = value
|
||||
self.comment: Optional[str] = comment
|
||||
self.ifcond: Tuple[str, ...] = tuple(ifcond)
|
||||
self.ifcond = ifcond
|
||||
|
||||
|
||||
def _tree_to_qlit(obj: JSONValue,
|
||||
@ -124,11 +123,11 @@ def _tree_to_qlit(obj: JSONValue,
|
||||
ret = ''
|
||||
if obj.comment:
|
||||
ret += indent(level) + f"/* {obj.comment} */\n"
|
||||
if obj.ifcond:
|
||||
ret += gen_if(obj.ifcond)
|
||||
if obj.ifcond.is_present():
|
||||
ret += gen_if(obj.ifcond.cgen())
|
||||
ret += _tree_to_qlit(obj.value, level)
|
||||
if obj.ifcond:
|
||||
ret += '\n' + gen_endif(obj.ifcond)
|
||||
if obj.ifcond.is_present():
|
||||
ret += '\n' + gen_endif(obj.ifcond.cgen())
|
||||
return ret
|
||||
|
||||
ret = ''
|
||||
@ -254,7 +253,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
return [Annotated(f.name, f.ifcond) for f in features]
|
||||
|
||||
def _gen_tree(self, name: str, mtype: str, obj: Dict[str, object],
|
||||
ifcond: Sequence[str] = (),
|
||||
ifcond: QAPISchemaIfCond = QAPISchemaIfCond(),
|
||||
features: Sequence[QAPISchemaFeature] = ()) -> None:
|
||||
"""
|
||||
Build and append a SchemaInfo object to self._trees.
|
||||
@ -305,7 +304,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
self._gen_tree(name, 'builtin', {'json-type': json_type})
|
||||
|
||||
def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
members: List[QAPISchemaEnumMember],
|
||||
prefix: Optional[str]) -> None:
|
||||
@ -316,14 +315,14 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
)
|
||||
|
||||
def visit_array_type(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
element_type: QAPISchemaType) -> None:
|
||||
element = self._use_type(element_type)
|
||||
self._gen_tree('[' + element + ']', 'array', {'element-type': element},
|
||||
ifcond)
|
||||
|
||||
def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
members: List[QAPISchemaObjectTypeMember],
|
||||
variants: Optional[QAPISchemaVariants]) -> None:
|
||||
@ -336,7 +335,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
self._gen_tree(name, 'object', obj, ifcond, features)
|
||||
|
||||
def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
variants: QAPISchemaVariants) -> None:
|
||||
self._gen_tree(
|
||||
@ -348,7 +347,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
)
|
||||
|
||||
def visit_command(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
arg_type: Optional[QAPISchemaObjectType],
|
||||
ret_type: Optional[QAPISchemaType], gen: bool,
|
||||
@ -367,7 +366,8 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||
self._gen_tree(name, 'command', obj, ifcond, features)
|
||||
|
||||
def visit_event(self, name: str, info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str], features: List[QAPISchemaFeature],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
arg_type: Optional[QAPISchemaObjectType],
|
||||
boxed: bool) -> None:
|
||||
assert self._schema is not None
|
||||
|
@ -19,12 +19,31 @@ import os
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from .common import POINTER_SUFFIX, c_name
|
||||
from .common import (
|
||||
POINTER_SUFFIX,
|
||||
c_name,
|
||||
cgen_ifcond,
|
||||
docgen_ifcond,
|
||||
)
|
||||
from .error import QAPIError, QAPISemError, QAPISourceError
|
||||
from .expr import check_exprs
|
||||
from .parser import QAPISchemaParser
|
||||
|
||||
|
||||
class QAPISchemaIfCond:
|
||||
def __init__(self, ifcond=None):
|
||||
self.ifcond = ifcond or {}
|
||||
|
||||
def cgen(self):
|
||||
return cgen_ifcond(self.ifcond)
|
||||
|
||||
def docgen(self):
|
||||
return docgen_ifcond(self.ifcond)
|
||||
|
||||
def is_present(self):
|
||||
return bool(self.ifcond)
|
||||
|
||||
|
||||
class QAPISchemaEntity:
|
||||
meta: Optional[str] = None
|
||||
|
||||
@ -42,7 +61,7 @@ class QAPISchemaEntity:
|
||||
# such place).
|
||||
self.info = info
|
||||
self.doc = doc
|
||||
self._ifcond = ifcond or []
|
||||
self._ifcond = ifcond or QAPISchemaIfCond()
|
||||
self.features = features or []
|
||||
self._checked = False
|
||||
|
||||
@ -593,7 +612,7 @@ class QAPISchemaVariants:
|
||||
self.info,
|
||||
"discriminator member '%s' of %s must not be optional"
|
||||
% (self._tag_name, base))
|
||||
if self.tag_member.ifcond:
|
||||
if self.tag_member.ifcond.is_present():
|
||||
raise QAPISemError(
|
||||
self.info,
|
||||
"discriminator member '%s' of %s must not be conditional"
|
||||
@ -601,7 +620,7 @@ class QAPISchemaVariants:
|
||||
else: # simple union
|
||||
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
|
||||
assert not self.tag_member.optional
|
||||
assert self.tag_member.ifcond == []
|
||||
assert not self.tag_member.ifcond.is_present()
|
||||
if self._tag_name: # flat union
|
||||
# branches that are not explicitly covered get an empty type
|
||||
cases = {v.name for v in self.variants}
|
||||
@ -646,7 +665,7 @@ class QAPISchemaMember:
|
||||
assert isinstance(name, str)
|
||||
self.name = name
|
||||
self.info = info
|
||||
self.ifcond = ifcond or []
|
||||
self.ifcond = ifcond or QAPISchemaIfCond()
|
||||
self.defined_in = None
|
||||
|
||||
def set_defined_in(self, name):
|
||||
@ -968,11 +987,13 @@ class QAPISchema:
|
||||
def _make_features(self, features, info):
|
||||
if features is None:
|
||||
return []
|
||||
return [QAPISchemaFeature(f['name'], info, f.get('if'))
|
||||
return [QAPISchemaFeature(f['name'], info,
|
||||
QAPISchemaIfCond(f.get('if')))
|
||||
for f in features]
|
||||
|
||||
def _make_enum_members(self, values, info):
|
||||
return [QAPISchemaEnumMember(v['name'], info, v.get('if'))
|
||||
return [QAPISchemaEnumMember(v['name'], info,
|
||||
QAPISchemaIfCond(v.get('if')))
|
||||
for v in values]
|
||||
|
||||
def _make_implicit_enum_type(self, name, info, ifcond, values):
|
||||
@ -997,18 +1018,18 @@ class QAPISchema:
|
||||
name = 'q_obj_%s-%s' % (name, role)
|
||||
typ = self.lookup_entity(name, QAPISchemaObjectType)
|
||||
if typ:
|
||||
# The implicit object type has multiple users. This can
|
||||
# happen only for simple unions' implicit wrapper types.
|
||||
# Its ifcond should be the disjunction of its user's
|
||||
# ifconds. Not implemented. Instead, we always pass the
|
||||
# wrapped type's ifcond, which is trivially the same for all
|
||||
# users. It's also necessary for the wrapper to compile.
|
||||
# But it's not tight: the disjunction need not imply it. We
|
||||
# may end up compiling useless wrapper types.
|
||||
# The implicit object type has multiple users. This is
|
||||
# either a duplicate definition (which will be flagged
|
||||
# later), or an implicit wrapper type used for multiple
|
||||
# simple unions. In the latter case, 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
|
||||
|
||||
# pylint: disable=protected-access
|
||||
assert (ifcond or []) == typ._ifcond
|
||||
pass
|
||||
else:
|
||||
self._def_entity(QAPISchemaObjectType(
|
||||
name, info, None, ifcond, None, None, members, None))
|
||||
@ -1018,7 +1039,7 @@ class QAPISchema:
|
||||
name = expr['enum']
|
||||
data = expr['data']
|
||||
prefix = expr.get('prefix')
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
self._def_entity(QAPISchemaEnumType(
|
||||
name, info, doc, ifcond, features,
|
||||
@ -1036,7 +1057,8 @@ class QAPISchema:
|
||||
self._make_features(features, info))
|
||||
|
||||
def _make_members(self, data, info):
|
||||
return [self._make_member(key, value['type'], value.get('if'),
|
||||
return [self._make_member(key, value['type'],
|
||||
QAPISchemaIfCond(value.get('if')),
|
||||
value.get('features'), info)
|
||||
for (key, value) in data.items()]
|
||||
|
||||
@ -1044,7 +1066,7 @@ class QAPISchema:
|
||||
name = expr['struct']
|
||||
base = expr.get('base')
|
||||
data = expr['data']
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
self._def_entity(QAPISchemaObjectType(
|
||||
name, info, doc, ifcond, features, base,
|
||||
@ -1067,7 +1089,7 @@ class QAPISchema:
|
||||
name = expr['union']
|
||||
data = expr['data']
|
||||
base = expr.get('base')
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
tag_name = expr.get('discriminator')
|
||||
tag_member = None
|
||||
@ -1076,15 +1098,19 @@ class QAPISchema:
|
||||
name, info, ifcond,
|
||||
'base', self._make_members(base, info))
|
||||
if tag_name:
|
||||
variants = [self._make_variant(key, value['type'],
|
||||
value.get('if'), info)
|
||||
variants = [
|
||||
self._make_variant(key, value['type'],
|
||||
QAPISchemaIfCond(value.get('if')),
|
||||
info)
|
||||
for (key, value) in data.items()]
|
||||
members = []
|
||||
else:
|
||||
variants = [self._make_simple_variant(key, value['type'],
|
||||
value.get('if'), info)
|
||||
variants = [
|
||||
self._make_simple_variant(key, value['type'],
|
||||
QAPISchemaIfCond(value.get('if')),
|
||||
info)
|
||||
for (key, value) in data.items()]
|
||||
enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
|
||||
enum = [{'name': v.name, 'if': v.ifcond.ifcond} for v in variants]
|
||||
typ = self._make_implicit_enum_type(name, info, ifcond, enum)
|
||||
tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
|
||||
members = [tag_member]
|
||||
@ -1097,9 +1123,11 @@ class QAPISchema:
|
||||
def _def_alternate_type(self, expr, info, doc):
|
||||
name = expr['alternate']
|
||||
data = expr['data']
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
variants = [self._make_variant(key, value['type'], value.get('if'),
|
||||
variants = [
|
||||
self._make_variant(key, value['type'],
|
||||
QAPISchemaIfCond(value.get('if')),
|
||||
info)
|
||||
for (key, value) in data.items()]
|
||||
tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False)
|
||||
@ -1118,7 +1146,7 @@ class QAPISchema:
|
||||
allow_oob = expr.get('allow-oob', False)
|
||||
allow_preconfig = expr.get('allow-preconfig', False)
|
||||
coroutine = expr.get('coroutine', False)
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
@ -1137,7 +1165,7 @@ class QAPISchema:
|
||||
name = expr['event']
|
||||
data = expr.get('data')
|
||||
boxed = expr.get('boxed', False)
|
||||
ifcond = expr.get('if')
|
||||
ifcond = QAPISchemaIfCond(expr.get('if'))
|
||||
features = self._make_features(expr.get('features'), info)
|
||||
if isinstance(data, OrderedDict):
|
||||
data = self._make_implicit_object_type(
|
||||
|
@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
|
||||
# See the COPYING file in the top-level directory.
|
||||
"""
|
||||
|
||||
from typing import List, Optional, Sequence
|
||||
from typing import List, Optional
|
||||
|
||||
from .common import (
|
||||
c_enum_const,
|
||||
@ -27,6 +27,7 @@ from .schema import (
|
||||
QAPISchema,
|
||||
QAPISchemaEnumMember,
|
||||
QAPISchemaFeature,
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaObjectType,
|
||||
QAPISchemaObjectTypeMember,
|
||||
QAPISchemaType,
|
||||
@ -50,13 +51,13 @@ const QEnumLookup %(c_name)s_lookup = {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
for memb in members:
|
||||
ret += gen_if(memb.ifcond)
|
||||
ret += gen_if(memb.ifcond.cgen())
|
||||
index = c_enum_const(name, memb.name, prefix)
|
||||
ret += mcgen('''
|
||||
[%(index)s] = "%(name)s",
|
||||
''',
|
||||
index=index, name=memb.name)
|
||||
ret += gen_endif(memb.ifcond)
|
||||
ret += gen_endif(memb.ifcond.cgen())
|
||||
|
||||
ret += mcgen('''
|
||||
},
|
||||
@ -80,12 +81,12 @@ typedef enum %(c_name)s {
|
||||
c_name=c_name(name))
|
||||
|
||||
for memb in enum_members:
|
||||
ret += gen_if(memb.ifcond)
|
||||
ret += gen_if(memb.ifcond.cgen())
|
||||
ret += mcgen('''
|
||||
%(c_enum)s,
|
||||
''',
|
||||
c_enum=c_enum_const(name, memb.name, prefix))
|
||||
ret += gen_endif(memb.ifcond)
|
||||
ret += gen_endif(memb.ifcond.cgen())
|
||||
|
||||
ret += mcgen('''
|
||||
} %(c_name)s;
|
||||
@ -125,7 +126,7 @@ struct %(c_name)s {
|
||||
def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
|
||||
ret = ''
|
||||
for memb in members:
|
||||
ret += gen_if(memb.ifcond)
|
||||
ret += gen_if(memb.ifcond.cgen())
|
||||
if memb.optional:
|
||||
ret += mcgen('''
|
||||
bool has_%(c_name)s;
|
||||
@ -135,11 +136,11 @@ def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
|
||||
%(c_type)s %(c_name)s;
|
||||
''',
|
||||
c_type=memb.type.c_type(), c_name=c_name(memb.name))
|
||||
ret += gen_endif(memb.ifcond)
|
||||
ret += gen_endif(memb.ifcond.cgen())
|
||||
return ret
|
||||
|
||||
|
||||
def gen_object(name: str, ifcond: Sequence[str],
|
||||
def gen_object(name: str, ifcond: QAPISchemaIfCond,
|
||||
base: Optional[QAPISchemaObjectType],
|
||||
members: List[QAPISchemaObjectTypeMember],
|
||||
variants: Optional[QAPISchemaVariants]) -> str:
|
||||
@ -158,7 +159,7 @@ def gen_object(name: str, ifcond: Sequence[str],
|
||||
ret += mcgen('''
|
||||
|
||||
''')
|
||||
ret += gen_if(ifcond)
|
||||
ret += gen_if(ifcond.cgen())
|
||||
ret += mcgen('''
|
||||
struct %(c_name)s {
|
||||
''',
|
||||
@ -192,7 +193,7 @@ struct %(c_name)s {
|
||||
ret += mcgen('''
|
||||
};
|
||||
''')
|
||||
ret += gen_endif(ifcond)
|
||||
ret += gen_endif(ifcond.cgen())
|
||||
|
||||
return ret
|
||||
|
||||
@ -219,13 +220,13 @@ def gen_variants(variants: QAPISchemaVariants) -> str:
|
||||
for var in variants.variants:
|
||||
if var.type.name == 'q_empty':
|
||||
continue
|
||||
ret += gen_if(var.ifcond)
|
||||
ret += gen_if(var.ifcond.cgen())
|
||||
ret += mcgen('''
|
||||
%(c_type)s %(c_name)s;
|
||||
''',
|
||||
c_type=var.type.c_unboxed_type(),
|
||||
c_name=c_name(var.name))
|
||||
ret += gen_endif(var.ifcond)
|
||||
ret += gen_endif(var.ifcond.cgen())
|
||||
|
||||
ret += mcgen('''
|
||||
} u;
|
||||
@ -307,7 +308,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_enum_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
members: List[QAPISchemaEnumMember],
|
||||
prefix: Optional[str]) -> None:
|
||||
@ -318,7 +319,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_array_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
element_type: QAPISchemaType) -> None:
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||
@ -328,7 +329,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_object_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
base: Optional[QAPISchemaObjectType],
|
||||
members: List[QAPISchemaObjectTypeMember],
|
||||
@ -351,7 +352,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_alternate_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
variants: QAPISchemaVariants) -> None:
|
||||
with ifcontext(ifcond, self._genh):
|
||||
|
@ -13,7 +13,7 @@ This work is licensed under the terms of the GNU GPL, version 2.
|
||||
See the COPYING file in the top-level directory.
|
||||
"""
|
||||
|
||||
from typing import List, Optional, Sequence
|
||||
from typing import List, Optional
|
||||
|
||||
from .common import (
|
||||
c_enum_const,
|
||||
@ -29,6 +29,7 @@ from .schema import (
|
||||
QAPISchemaEnumMember,
|
||||
QAPISchemaEnumType,
|
||||
QAPISchemaFeature,
|
||||
QAPISchemaIfCond,
|
||||
QAPISchemaObjectType,
|
||||
QAPISchemaObjectTypeMember,
|
||||
QAPISchemaType,
|
||||
@ -78,7 +79,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
|
||||
for memb in members:
|
||||
deprecated = 'deprecated' in [f.name for f in memb.features]
|
||||
ret += gen_if(memb.ifcond)
|
||||
ret += gen_if(memb.ifcond.cgen())
|
||||
if memb.optional:
|
||||
ret += mcgen('''
|
||||
if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) {
|
||||
@ -111,7 +112,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
ret += mcgen('''
|
||||
}
|
||||
''')
|
||||
ret += gen_endif(memb.ifcond)
|
||||
ret += gen_endif(memb.ifcond.cgen())
|
||||
|
||||
if variants:
|
||||
tag_member = variants.tag_member
|
||||
@ -125,7 +126,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
for var in variants.variants:
|
||||
case_str = c_enum_const(tag_member.type.name, var.name,
|
||||
tag_member.type.prefix)
|
||||
ret += gen_if(var.ifcond)
|
||||
ret += gen_if(var.ifcond.cgen())
|
||||
if var.type.name == 'q_empty':
|
||||
# valid variant and nothing to do
|
||||
ret += mcgen('''
|
||||
@ -141,7 +142,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
case=case_str,
|
||||
c_type=var.type.c_name(), c_name=c_name(var.name))
|
||||
|
||||
ret += gen_endif(var.ifcond)
|
||||
ret += gen_endif(var.ifcond.cgen())
|
||||
ret += mcgen('''
|
||||
default:
|
||||
abort();
|
||||
@ -227,7 +228,7 @@ bool visit_type_%(c_name)s(Visitor *v, const char *name,
|
||||
c_name=c_name(name))
|
||||
|
||||
for var in variants.variants:
|
||||
ret += gen_if(var.ifcond)
|
||||
ret += gen_if(var.ifcond.cgen())
|
||||
ret += mcgen('''
|
||||
case %(case)s:
|
||||
''',
|
||||
@ -253,7 +254,7 @@ bool visit_type_%(c_name)s(Visitor *v, const char *name,
|
||||
ret += mcgen('''
|
||||
break;
|
||||
''')
|
||||
ret += gen_endif(var.ifcond)
|
||||
ret += gen_endif(var.ifcond.cgen())
|
||||
|
||||
ret += mcgen('''
|
||||
case QTYPE_NONE:
|
||||
@ -352,7 +353,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_enum_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
members: List[QAPISchemaEnumMember],
|
||||
prefix: Optional[str]) -> None:
|
||||
@ -363,7 +364,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_array_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
element_type: QAPISchemaType) -> None:
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
self._genh.add(gen_visit_decl(name))
|
||||
@ -372,7 +373,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_object_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
base: Optional[QAPISchemaObjectType],
|
||||
members: List[QAPISchemaObjectTypeMember],
|
||||
@ -394,7 +395,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||
def visit_alternate_type(self,
|
||||
name: str,
|
||||
info: Optional[QAPISourceInfo],
|
||||
ifcond: Sequence[str],
|
||||
ifcond: QAPISchemaIfCond,
|
||||
features: List[QAPISchemaFeature],
|
||||
variants: QAPISchemaVariants) -> None:
|
||||
with ifcontext(ifcond, self._genh, self._genc):
|
||||
|
@ -1,2 +1,2 @@
|
||||
alternate-branch-if-invalid.json: In alternate 'Alt':
|
||||
alternate-branch-if-invalid.json:2: 'if' condition ' ' of 'data' member 'branch' makes no sense
|
||||
alternate-branch-if-invalid.json:2: 'if' condition ' ' of 'data' member 'branch' is not a valid identifier
|
||||
|
2
tests/qapi-schema/bad-if-all.err
Normal file
2
tests/qapi-schema/bad-if-all.err
Normal file
@ -0,0 +1,2 @@
|
||||
bad-if-all.json: In struct 'TestIfStruct':
|
||||
bad-if-all.json:2: 'all' condition of struct must be an array
|
3
tests/qapi-schema/bad-if-all.json
Normal file
3
tests/qapi-schema/bad-if-all.json
Normal file
@ -0,0 +1,3 @@
|
||||
# check 'if all' is not a list
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'all': 'ALL' } }
|
0
tests/qapi-schema/bad-if-all.out
Normal file
0
tests/qapi-schema/bad-if-all.out
Normal file
@ -1,3 +1,3 @@
|
||||
# check empty 'if' list
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': [] }
|
||||
'if': { 'all': [] } }
|
||||
|
@ -1,2 +1,2 @@
|
||||
bad-if-empty.json: In struct 'TestIfStruct':
|
||||
bad-if-empty.json:2: 'if' condition '' of struct makes no sense
|
||||
bad-if-empty.json:2: 'if' condition '' of struct is not a valid identifier
|
||||
|
3
tests/qapi-schema/bad-if-key.err
Normal file
3
tests/qapi-schema/bad-if-key.err
Normal file
@ -0,0 +1,3 @@
|
||||
bad-if-key.json: In struct 'TestIfStruct':
|
||||
bad-if-key.json:2: 'if' condition has unknown key 'value'
|
||||
Valid keys are 'all', 'any', 'not'.
|
3
tests/qapi-schema/bad-if-key.json
Normal file
3
tests/qapi-schema/bad-if-key.json
Normal file
@ -0,0 +1,3 @@
|
||||
# check unknown 'if' dict key
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
|
0
tests/qapi-schema/bad-if-key.out
Normal file
0
tests/qapi-schema/bad-if-key.out
Normal file
2
tests/qapi-schema/bad-if-keys.err
Normal file
2
tests/qapi-schema/bad-if-keys.err
Normal file
@ -0,0 +1,2 @@
|
||||
bad-if-keys.json: In struct 'TestIfStruct':
|
||||
bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all', 'any' or 'not'
|
3
tests/qapi-schema/bad-if-keys.json
Normal file
3
tests/qapi-schema/bad-if-keys.json
Normal file
@ -0,0 +1,3 @@
|
||||
# check multiple 'if' keys
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'any': ['ANY'], 'all': ['ALL'] } }
|
0
tests/qapi-schema/bad-if-keys.out
Normal file
0
tests/qapi-schema/bad-if-keys.out
Normal file
@ -1,2 +1,2 @@
|
||||
bad-if-list.json: In struct 'TestIfStruct':
|
||||
bad-if-list.json:2: 'if' condition ' ' of struct makes no sense
|
||||
bad-if-list.json:2: 'if' condition 'foo' of struct is not a valid identifier
|
||||
|
@ -1,3 +1,3 @@
|
||||
# check invalid 'if' content
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': ['foo', ' '] }
|
||||
'if': { 'all': ['foo', ' '] } }
|
||||
|
@ -1,2 +1,2 @@
|
||||
bad-if.json: In struct 'TestIfStruct':
|
||||
bad-if.json:2: 'if' condition of struct must be a string or a list of strings
|
||||
bad-if.json:2: 'if' condition of struct must be a string or an object
|
||||
|
@ -1,3 +1,3 @@
|
||||
# check invalid 'if' type
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
|
||||
'if': ['TEST_IF_STRUCT'] }
|
||||
|
@ -61,16 +61,17 @@
|
||||
# @two is undocumented
|
||||
##
|
||||
{ 'enum': 'Enum', 'data':
|
||||
[ { 'name': 'one', 'if': 'defined(IFONE)' }, 'two' ],
|
||||
[ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
|
||||
'features': [ 'enum-feat' ],
|
||||
'if': 'defined(IFCOND)' }
|
||||
'if': 'IFCOND' }
|
||||
|
||||
##
|
||||
# @Base:
|
||||
# @base1:
|
||||
# the first member
|
||||
##
|
||||
{ 'struct': 'Base', 'data': { 'base1': 'Enum' } }
|
||||
{ 'struct': 'Base', 'data': { 'base1': 'Enum' },
|
||||
'if': { 'all': ['IFALL1', 'IFALL2'] } }
|
||||
|
||||
##
|
||||
# @Variant1:
|
||||
@ -86,7 +87,7 @@
|
||||
'features': [ 'variant1-feat' ],
|
||||
'data': { 'var1': { 'type': 'str',
|
||||
'features': [ 'member-feat' ],
|
||||
'if': 'defined(IFSTR)' } } }
|
||||
'if': 'IFSTR' } } }
|
||||
|
||||
##
|
||||
# @Variant2:
|
||||
@ -102,7 +103,9 @@
|
||||
'features': [ 'union-feat1' ],
|
||||
'base': 'Base',
|
||||
'discriminator': 'base1',
|
||||
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
|
||||
'data': { 'one': 'Variant1',
|
||||
'two': { 'type': 'Variant2',
|
||||
'if': { 'any': ['IFONE', 'IFTWO'] } } } }
|
||||
|
||||
##
|
||||
# @SugaredUnion:
|
||||
@ -123,7 +126,8 @@
|
||||
##
|
||||
{ 'alternate': 'Alternate',
|
||||
'features': [ 'alt-feat' ],
|
||||
'data': { 'i': 'int', 'b': 'bool' } }
|
||||
'data': { 'i': 'int', 'b': 'bool' },
|
||||
'if': { 'not': 'IFNOT' } }
|
||||
|
||||
##
|
||||
# == Another subsection
|
||||
|
@ -12,15 +12,16 @@ enum QType
|
||||
module doc-good.json
|
||||
enum Enum
|
||||
member one
|
||||
if ['defined(IFONE)']
|
||||
if IFONE
|
||||
member two
|
||||
if ['defined(IFCOND)']
|
||||
if IFCOND
|
||||
feature enum-feat
|
||||
object Base
|
||||
member base1: Enum optional=False
|
||||
if OrderedDict([('all', ['IFALL1', 'IFALL2'])])
|
||||
object Variant1
|
||||
member var1: str optional=False
|
||||
if ['defined(IFSTR)']
|
||||
if IFSTR
|
||||
feature member-feat
|
||||
feature variant1-feat
|
||||
object Variant2
|
||||
@ -29,7 +30,7 @@ object Object
|
||||
tag base1
|
||||
case one: Variant1
|
||||
case two: Variant2
|
||||
if ['IFTWO']
|
||||
if OrderedDict([('any', ['IFONE', 'IFTWO'])])
|
||||
feature union-feat1
|
||||
object q_obj_Variant1-wrapper
|
||||
member data: Variant1 optional=False
|
||||
@ -38,18 +39,19 @@ object q_obj_Variant2-wrapper
|
||||
enum SugaredUnionKind
|
||||
member one
|
||||
member two
|
||||
if ['IFTWO']
|
||||
if IFTWO
|
||||
object SugaredUnion
|
||||
member type: SugaredUnionKind optional=False
|
||||
tag type
|
||||
case one: q_obj_Variant1-wrapper
|
||||
case two: q_obj_Variant2-wrapper
|
||||
if ['IFTWO']
|
||||
if IFTWO
|
||||
feature union-feat2
|
||||
alternate Alternate
|
||||
tag type
|
||||
case i: int
|
||||
case b: bool
|
||||
if OrderedDict([('not', 'IFNOT')])
|
||||
feature alt-feat
|
||||
object q_obj_cmd-arg
|
||||
member arg1: int optional=False
|
||||
|
@ -43,7 +43,7 @@ Example:
|
||||
Values
|
||||
~~~~~~
|
||||
|
||||
"one" (**If: **"defined(IFONE)")
|
||||
"one" (**If: **"IFONE")
|
||||
The _one_ {and only}
|
||||
|
||||
"two"
|
||||
@ -62,7 +62,7 @@ Features
|
||||
If
|
||||
~~
|
||||
|
||||
"defined(IFCOND)"
|
||||
"IFCOND"
|
||||
|
||||
|
||||
"Base" (Object)
|
||||
@ -76,6 +76,12 @@ Members
|
||||
the first member
|
||||
|
||||
|
||||
If
|
||||
~~
|
||||
|
||||
"(IFALL1 and IFALL2)"
|
||||
|
||||
|
||||
"Variant1" (Object)
|
||||
-------------------
|
||||
|
||||
@ -87,7 +93,7 @@ Another paragraph (but no "var": line)
|
||||
Members
|
||||
~~~~~~~
|
||||
|
||||
"var1": "string" (**If: **"defined(IFSTR)")
|
||||
"var1": "string" (**If: **"IFSTR")
|
||||
Not documented
|
||||
|
||||
|
||||
@ -114,7 +120,8 @@ Members
|
||||
|
||||
The members of "Base"
|
||||
The members of "Variant1" when "base1" is ""one""
|
||||
The members of "Variant2" when "base1" is ""two"" (**If: **"IFTWO")
|
||||
The members of "Variant2" when "base1" is ""two"" (**If: **"(IFONE or
|
||||
IFTWO)")
|
||||
|
||||
Features
|
||||
~~~~~~~~
|
||||
@ -164,6 +171,12 @@ Features
|
||||
a feature
|
||||
|
||||
|
||||
If
|
||||
~~
|
||||
|
||||
"!IFNOT"
|
||||
|
||||
|
||||
Another subsection
|
||||
==================
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
enum-if-invalid.json: In enum 'TestIfEnum':
|
||||
enum-if-invalid.json:2: 'if' condition of 'data' member 'bar' must be a string or a list of strings
|
||||
enum-if-invalid.json:2: 'if' condition has unknown key 'val'
|
||||
Valid keys are 'all', 'any', 'not'.
|
||||
|
@ -1,2 +1,2 @@
|
||||
features-if-invalid.json: In struct 'Stru':
|
||||
features-if-invalid.json:2: 'if' condition of 'features' member 'f' must be a string or a list of strings
|
||||
features-if-invalid.json:2: 'if' condition of 'features' member 'f' must be a string or an object
|
||||
|
@ -1,3 +1,3 @@
|
||||
{ 'struct': 'FeatureStruct0',
|
||||
'data': { 'foo': 'int' },
|
||||
'features': [ { 'if': 'defined(NAMELESS_FEATURES)' } ] }
|
||||
'features': [ { 'if': 'NAMELESS_FEATURES' } ] }
|
||||
|
@ -37,8 +37,11 @@ schemas = [
|
||||
'bad-data.json',
|
||||
'bad-ident.json',
|
||||
'bad-if.json',
|
||||
'bad-if-all.json',
|
||||
'bad-if-empty.json',
|
||||
'bad-if-empty-list.json',
|
||||
'bad-if-key.json',
|
||||
'bad-if-keys.json',
|
||||
'bad-if-list.json',
|
||||
'bad-type-bool.json',
|
||||
'bad-type-dict.json',
|
||||
|
@ -222,44 +222,45 @@
|
||||
|
||||
{ 'struct': 'TestIfStruct', 'data':
|
||||
{ 'foo': 'int',
|
||||
'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} },
|
||||
'if': 'defined(TEST_IF_STRUCT)' }
|
||||
'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
|
||||
'if': 'TEST_IF_STRUCT' }
|
||||
|
||||
{ 'enum': 'TestIfEnum', 'data':
|
||||
[ 'foo', { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ],
|
||||
'if': 'defined(TEST_IF_ENUM)' }
|
||||
[ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
|
||||
'if': 'TEST_IF_ENUM' }
|
||||
|
||||
{ 'union': 'TestIfUnion', 'data':
|
||||
{ 'foo': 'TestStruct',
|
||||
'bar': { 'type': 'str', 'if': 'defined(TEST_IF_UNION_BAR)'} },
|
||||
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' }
|
||||
'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
|
||||
'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
|
||||
|
||||
{ 'command': 'test-if-union-cmd',
|
||||
'data': { 'union-cmd-arg': 'TestIfUnion' },
|
||||
'if': 'defined(TEST_IF_UNION)' }
|
||||
'if': 'TEST_IF_UNION' }
|
||||
|
||||
{ 'alternate': 'TestIfAlternate', 'data':
|
||||
{ 'foo': 'int',
|
||||
'bar': { 'type': 'TestStruct', 'if': 'defined(TEST_IF_ALT_BAR)'} },
|
||||
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' }
|
||||
'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
|
||||
'if': { 'all': ['TEST_IF_ALT', 'TEST_IF_STRUCT'] } }
|
||||
|
||||
{ 'command': 'test-if-alternate-cmd',
|
||||
'data': { 'alt-cmd-arg': 'TestIfAlternate' },
|
||||
'if': 'defined(TEST_IF_ALT)' }
|
||||
'if': { 'all': ['TEST_IF_ALT',
|
||||
{'not': 'TEST_IF_NOT_ALT'}] } }
|
||||
|
||||
{ 'command': 'test-if-cmd',
|
||||
'data': {
|
||||
'foo': 'TestIfStruct',
|
||||
'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_CMD_BAR)' } },
|
||||
'bar': { 'type': 'TestIfEnum', 'if': 'TEST_IF_CMD_BAR' } },
|
||||
'returns': 'UserDefThree',
|
||||
'if': ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] }
|
||||
'if': { 'all': ['TEST_IF_CMD', 'TEST_IF_STRUCT'] } }
|
||||
|
||||
{ 'command': 'test-cmd-return-def-three', 'returns': 'UserDefThree' }
|
||||
|
||||
{ 'event': 'TEST_IF_EVENT', 'data':
|
||||
{ 'foo': 'TestIfStruct',
|
||||
'bar': { 'type': ['TestIfEnum'], 'if': 'defined(TEST_IF_EVT_BAR)' } },
|
||||
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
|
||||
'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
|
||||
'if': { 'all': ['TEST_IF_EVT', 'TEST_IF_STRUCT'] } }
|
||||
|
||||
# test 'features'
|
||||
|
||||
@ -281,15 +282,21 @@
|
||||
|
||||
{ 'struct': 'CondFeatureStruct1',
|
||||
'data': { 'foo': 'int' },
|
||||
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'} ] }
|
||||
'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'} ] }
|
||||
{ 'struct': 'CondFeatureStruct2',
|
||||
'data': { 'foo': 'int' },
|
||||
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'},
|
||||
{ 'name': 'feature2', 'if': 'defined(TEST_IF_FEATURE_2)'} ] }
|
||||
'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'},
|
||||
{ 'name': 'feature2', 'if': 'TEST_IF_FEATURE_2'} ] }
|
||||
{ 'struct': 'CondFeatureStruct3',
|
||||
'data': { 'foo': 'int' },
|
||||
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
||||
'defined(TEST_IF_COND_2)'] } ] }
|
||||
'features': [ { 'name': 'feature1',
|
||||
'if': { 'all': [ 'TEST_IF_COND_1',
|
||||
'TEST_IF_COND_2'] } } ] }
|
||||
{ 'struct': 'CondFeatureStruct4',
|
||||
'data': { 'foo': 'int' },
|
||||
'features': [ { 'name': 'feature1',
|
||||
'if': {'any': ['TEST_IF_COND_1',
|
||||
'TEST_IF_COND_2'] } } ] }
|
||||
|
||||
{ 'enum': 'FeatureEnum1',
|
||||
'data': [ 'eins', 'zwei', 'drei' ],
|
||||
@ -313,7 +320,8 @@
|
||||
'*fs4': 'FeatureStruct4',
|
||||
'*cfs1': 'CondFeatureStruct1',
|
||||
'*cfs2': 'CondFeatureStruct2',
|
||||
'*cfs3': 'CondFeatureStruct3' },
|
||||
'*cfs3': 'CondFeatureStruct3',
|
||||
'*cfs4': 'CondFeatureStruct4' },
|
||||
'returns': 'FeatureStruct1',
|
||||
'features': [] }
|
||||
|
||||
@ -323,13 +331,14 @@
|
||||
'features': [ 'feature1', 'feature2' ] }
|
||||
|
||||
{ 'command': 'test-command-cond-features1',
|
||||
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'} ] }
|
||||
'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'} ] }
|
||||
{ 'command': 'test-command-cond-features2',
|
||||
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'},
|
||||
{ 'name': 'feature2', 'if': 'defined(TEST_IF_FEATURE_2)'} ] }
|
||||
'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'},
|
||||
{ 'name': 'feature2', 'if': 'TEST_IF_FEATURE_2'} ] }
|
||||
{ 'command': 'test-command-cond-features3',
|
||||
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
||||
'defined(TEST_IF_COND_2)'] } ] }
|
||||
'features': [ { 'name': 'feature1',
|
||||
'if': { 'all': [ 'TEST_IF_COND_1',
|
||||
'TEST_IF_COND_2'] } } ] }
|
||||
|
||||
{ 'event': 'TEST_EVENT_FEATURES0',
|
||||
'data': 'FeatureStruct1' }
|
||||
|
@ -298,65 +298,65 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
|
||||
object TestIfStruct
|
||||
member foo: int optional=False
|
||||
member bar: int optional=False
|
||||
if ['defined(TEST_IF_STRUCT_BAR)']
|
||||
if ['defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_STRUCT_BAR
|
||||
if TEST_IF_STRUCT
|
||||
enum TestIfEnum
|
||||
member foo
|
||||
member bar
|
||||
if ['defined(TEST_IF_ENUM_BAR)']
|
||||
if ['defined(TEST_IF_ENUM)']
|
||||
if TEST_IF_ENUM_BAR
|
||||
if TEST_IF_ENUM
|
||||
object q_obj_TestStruct-wrapper
|
||||
member data: TestStruct optional=False
|
||||
enum TestIfUnionKind
|
||||
member foo
|
||||
member bar
|
||||
if ['defined(TEST_IF_UNION_BAR)']
|
||||
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_UNION_BAR
|
||||
if OrderedDict([('all', ['TEST_IF_UNION', 'TEST_IF_STRUCT'])])
|
||||
object TestIfUnion
|
||||
member type: TestIfUnionKind optional=False
|
||||
tag type
|
||||
case foo: q_obj_TestStruct-wrapper
|
||||
case bar: q_obj_str-wrapper
|
||||
if ['defined(TEST_IF_UNION_BAR)']
|
||||
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_UNION_BAR
|
||||
if OrderedDict([('all', ['TEST_IF_UNION', 'TEST_IF_STRUCT'])])
|
||||
object q_obj_test-if-union-cmd-arg
|
||||
member union-cmd-arg: TestIfUnion optional=False
|
||||
if ['defined(TEST_IF_UNION)']
|
||||
if TEST_IF_UNION
|
||||
command test-if-union-cmd q_obj_test-if-union-cmd-arg -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
if ['defined(TEST_IF_UNION)']
|
||||
if TEST_IF_UNION
|
||||
alternate TestIfAlternate
|
||||
tag type
|
||||
case foo: int
|
||||
case bar: TestStruct
|
||||
if ['defined(TEST_IF_ALT_BAR)']
|
||||
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_ALT_BAR
|
||||
if OrderedDict([('all', ['TEST_IF_ALT', 'TEST_IF_STRUCT'])])
|
||||
object q_obj_test-if-alternate-cmd-arg
|
||||
member alt-cmd-arg: TestIfAlternate optional=False
|
||||
if ['defined(TEST_IF_ALT)']
|
||||
if OrderedDict([('all', ['TEST_IF_ALT', OrderedDict([('not', 'TEST_IF_NOT_ALT')])])])
|
||||
command test-if-alternate-cmd q_obj_test-if-alternate-cmd-arg -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
if ['defined(TEST_IF_ALT)']
|
||||
if OrderedDict([('all', ['TEST_IF_ALT', OrderedDict([('not', 'TEST_IF_NOT_ALT')])])])
|
||||
object q_obj_test-if-cmd-arg
|
||||
member foo: TestIfStruct optional=False
|
||||
member bar: TestIfEnum optional=False
|
||||
if ['defined(TEST_IF_CMD_BAR)']
|
||||
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_CMD_BAR
|
||||
if OrderedDict([('all', ['TEST_IF_CMD', 'TEST_IF_STRUCT'])])
|
||||
command test-if-cmd q_obj_test-if-cmd-arg -> UserDefThree
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
|
||||
if OrderedDict([('all', ['TEST_IF_CMD', 'TEST_IF_STRUCT'])])
|
||||
command test-cmd-return-def-three None -> UserDefThree
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
array TestIfEnumList TestIfEnum
|
||||
if ['defined(TEST_IF_ENUM)']
|
||||
if TEST_IF_ENUM
|
||||
object q_obj_TEST_IF_EVENT-arg
|
||||
member foo: TestIfStruct optional=False
|
||||
member bar: TestIfEnumList optional=False
|
||||
if ['defined(TEST_IF_EVT_BAR)']
|
||||
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
|
||||
if TEST_IF_EVT_BAR
|
||||
if OrderedDict([('all', ['TEST_IF_EVT', 'TEST_IF_STRUCT'])])
|
||||
event TEST_IF_EVENT q_obj_TEST_IF_EVENT-arg
|
||||
boxed=False
|
||||
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
|
||||
if OrderedDict([('all', ['TEST_IF_EVT', 'TEST_IF_STRUCT'])])
|
||||
object FeatureStruct0
|
||||
member foo: int optional=False
|
||||
object FeatureStruct1
|
||||
@ -379,17 +379,21 @@ object FeatureStruct4
|
||||
object CondFeatureStruct1
|
||||
member foo: int optional=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_FEATURE_1)']
|
||||
if TEST_IF_FEATURE_1
|
||||
object CondFeatureStruct2
|
||||
member foo: int optional=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_FEATURE_1)']
|
||||
if TEST_IF_FEATURE_1
|
||||
feature feature2
|
||||
if ['defined(TEST_IF_FEATURE_2)']
|
||||
if TEST_IF_FEATURE_2
|
||||
object CondFeatureStruct3
|
||||
member foo: int optional=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
||||
if OrderedDict([('all', ['TEST_IF_COND_1', 'TEST_IF_COND_2'])])
|
||||
object CondFeatureStruct4
|
||||
member foo: int optional=False
|
||||
feature feature1
|
||||
if OrderedDict([('any', ['TEST_IF_COND_1', 'TEST_IF_COND_2'])])
|
||||
enum FeatureEnum1
|
||||
member eins
|
||||
member zwei
|
||||
@ -417,6 +421,7 @@ object q_obj_test-features0-arg
|
||||
member cfs1: CondFeatureStruct1 optional=True
|
||||
member cfs2: CondFeatureStruct2 optional=True
|
||||
member cfs3: CondFeatureStruct3 optional=True
|
||||
member cfs4: CondFeatureStruct4 optional=True
|
||||
command test-features0 q_obj_test-features0-arg -> FeatureStruct1
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
command test-command-features1 None -> None
|
||||
@ -429,17 +434,17 @@ command test-command-features3 None -> None
|
||||
command test-command-cond-features1 None -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_FEATURE_1)']
|
||||
if TEST_IF_FEATURE_1
|
||||
command test-command-cond-features2 None -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_FEATURE_1)']
|
||||
if TEST_IF_FEATURE_1
|
||||
feature feature2
|
||||
if ['defined(TEST_IF_FEATURE_2)']
|
||||
if TEST_IF_FEATURE_2
|
||||
command test-command-cond-features3 None -> None
|
||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||
feature feature1
|
||||
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
||||
if OrderedDict([('all', ['TEST_IF_COND_1', 'TEST_IF_COND_2'])])
|
||||
event TEST_EVENT_FEATURES0 FeatureStruct1
|
||||
boxed=False
|
||||
event TEST_EVENT_FEATURES1 None
|
||||
|
@ -1,3 +1,3 @@
|
||||
# we reject duplicate events
|
||||
{ 'event': 'EVENT_A', 'data': { 'myint': 'int' } }
|
||||
{ 'event': 'EVENT_A', 'data': { 'myint': 'int' } }
|
||||
{ 'event': 'EVENT_A', 'data': { 'myint': 'int' }, 'if': 'FOO' }
|
||||
|
@ -1,2 +1,2 @@
|
||||
struct-member-if-invalid.json: In struct 'Stru':
|
||||
struct-member-if-invalid.json:2: 'if' condition of 'data' member 'member' must be a string or a list of strings
|
||||
struct-member-if-invalid.json:2: 'if' condition of 'data' member 'member' must be a string or an object
|
||||
|
@ -94,8 +94,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||
|
||||
@staticmethod
|
||||
def _print_if(ifcond, indent=4):
|
||||
if ifcond:
|
||||
print('%sif %s' % (' ' * indent, ifcond))
|
||||
if ifcond.is_present():
|
||||
print('%sif %s' % (' ' * indent, ifcond.ifcond))
|
||||
|
||||
@classmethod
|
||||
def _print_features(cls, features, indent=4):
|
||||
|
@ -1,2 +1,2 @@
|
||||
union-branch-if-invalid.json: In union 'Uni':
|
||||
union-branch-if-invalid.json:4: 'if' condition '' of 'data' member 'branch1' makes no sense
|
||||
union-branch-if-invalid.json:4: 'if' condition '' of 'data' member 'branch1' is not a valid identifier
|
||||
|
@ -3,4 +3,4 @@
|
||||
{ 'struct': 'Stru', 'data': { 'member': 'str' } }
|
||||
{ 'union': 'Uni',
|
||||
'base': { 'tag': 'Branches' }, 'discriminator': 'tag',
|
||||
'data': { 'branch1': { 'type': 'Stru', 'if': [''] } } }
|
||||
'data': { 'branch1': { 'type': 'Stru', 'if': { 'all': [''] } } } }
|
||||
|
@ -51,6 +51,7 @@ FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0,
|
||||
bool has_cfs1, CondFeatureStruct1 *cfs1,
|
||||
bool has_cfs2, CondFeatureStruct2 *cfs2,
|
||||
bool has_cfs3, CondFeatureStruct3 *cfs3,
|
||||
bool has_cfs4, CondFeatureStruct4 *cfs4,
|
||||
Error **errp)
|
||||
{
|
||||
return g_new0(FeatureStruct1, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user