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>
staging
Peter Maydell 2021-08-26 13:42:34 +01:00
commit c83fcfaf8a
53 changed files with 505 additions and 344 deletions

View File

@ -826,25 +826,31 @@ Configuring the schema
Syntax:: Syntax::
COND = STRING COND = STRING
| [ STRING, ... ] | { 'all: [ COND, ... ] }
| { 'any: [ COND, ... ] }
| { 'not': COND }
All definitions take an optional 'if' member. Its value must be a 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 string, or an object with a single member 'all', 'any' or 'not'.
containing just that string. The code generated for the definition
will then be guarded by #if STRING for each STRING in the COND list. 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 :: Example: a conditional struct ::
{ 'struct': 'IfStruct', 'data': { 'foo': 'int' }, { '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:: gets its generated code guarded like this::
#if defined(CONFIG_FOO) #if defined(CONFIG_FOO) && defined(HAVE_BAR)
#if defined(HAVE_BAR)
... generated code ... ... generated code ...
#endif /* defined(HAVE_BAR) */ #endif /* defined(HAVE_BAR) && defined(CONFIG_FOO) */
#endif /* defined(CONFIG_FOO) */
Individual members of complex types, commands arguments, and Individual members of complex types, commands arguments, and
event-specific data can also be made conditional. This requires the event-specific data can also be made conditional. This requires the
@ -855,7 +861,7 @@ member 'bar' ::
{ 'struct': 'IfStruct', 'data': { 'struct': 'IfStruct', 'data':
{ 'foo': 'int', { 'foo': 'int',
'bar': { 'type': 'int', 'if': 'defined(IFCOND)'} } } 'bar': { 'type': 'int', 'if': 'IFCOND'} } }
A union's discriminator may not be conditional. A union's discriminator may not be conditional.
@ -867,7 +873,7 @@ value 'bar' ::
{ 'enum': 'IfEnum', 'data': { 'enum': 'IfEnum', 'data':
[ 'foo', [ 'foo',
{ 'name' : 'bar', 'if': 'defined(IFCOND)' } ] } { 'name' : 'bar', 'if': 'IFCOND' } ] }
Likewise, features can be conditional. This requires the longhand Likewise, features can be conditional. This requires the longhand
form of FEATURE_. form of FEATURE_.
@ -877,7 +883,7 @@ Example: a struct with conditional feature 'allow-negative-numbers' ::
{ 'struct': 'TestType', { 'struct': 'TestType',
'data': { 'number': 'int' }, 'data': { 'number': 'int' },
'features': [ { 'name': 'allow-negative-numbers', 'features': [ { 'name': 'allow-negative-numbers',
'if': 'defined(IFCOND)' } ] } 'if': 'IFCOND' } ] }
Please note that you are responsible to ensure that the C code will Please note that you are responsible to ensure that the C code will
compile with an arbitrary combination of conditions, since the compile with an arbitrary combination of conditions, since the

View File

@ -112,17 +112,19 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
def _nodes_for_ifcond(self, ifcond, with_if=True): def _nodes_for_ifcond(self, ifcond, with_if=True):
"""Return list of Text, literal nodes for the ifcond """Return list of Text, literal nodes for the ifcond
Return a list which gives text like ' (If: cond1, cond2, cond3)', where Return a list which gives text like ' (If: condition)'.
the conditions are in literal-text and the commas are not.
If with_if is False, we don't return the "(If: " and ")". 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: if not with_if:
return condlist return [doc]
nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')] nodelist = [nodes.Text(' ('), nodes.strong('', 'If: ')]
nodelist.extend(condlist) nodelist.append(doc)
nodelist.append(nodes.Text(')')) nodelist.append(nodes.Text(')'))
return nodelist return nodelist
@ -139,7 +141,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
term.append(nodes.literal('', member.type.doc_type())) term.append(nodes.literal('', member.type.doc_type()))
if member.optional: if member.optional:
term.append(nodes.Text(' (optional)')) term.append(nodes.Text(' (optional)'))
if member.ifcond: if member.ifcond.is_present():
term.extend(self._nodes_for_ifcond(member.ifcond)) term.extend(self._nodes_for_ifcond(member.ifcond))
return term return term
@ -154,7 +156,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
nodes.literal('', variants.tag_member.name), nodes.literal('', variants.tag_member.name),
nodes.Text(' is '), nodes.Text(' is '),
nodes.literal('', '"%s"' % variant.name)] nodes.literal('', '"%s"' % variant.name)]
if variant.ifcond: if variant.ifcond.is_present():
term.extend(self._nodes_for_ifcond(variant.ifcond)) term.extend(self._nodes_for_ifcond(variant.ifcond))
return term return term
@ -209,7 +211,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
dlnode = nodes.definition_list() dlnode = nodes.definition_list()
for section in doc.args.values(): for section in doc.args.values():
termtext = [nodes.literal('', section.member.name)] 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)) termtext.extend(self._nodes_for_ifcond(section.member.ifcond))
# TODO drop fallbacks when undocumented members are outlawed # TODO drop fallbacks when undocumented members are outlawed
if section.text: if section.text:
@ -277,7 +279,7 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
def _nodes_for_if_section(self, ifcond): def _nodes_for_if_section(self, ifcond):
"""Return list of doctree nodes for the "If" section""" """Return list of doctree nodes for the "If" section"""
nodelist = [] nodelist = []
if ifcond: if ifcond.is_present():
snode = self._make_section('If') snode = self._make_section('If')
snode += nodes.paragraph( snode += nodes.paragraph(
'', '', *self._nodes_for_ifcond(ifcond, with_if=False) '', '', *self._nodes_for_ifcond(ifcond, with_if=False)

View File

@ -914,7 +914,7 @@
'data': { 'data': {
'file': 'BlockStatsSpecificFile', 'file': 'BlockStatsSpecificFile',
'host_device': { 'type': 'BlockStatsSpecificFile', 'host_device': { 'type': 'BlockStatsSpecificFile',
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' }, 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'nvme': 'BlockStatsSpecificNvme' } } 'nvme': 'BlockStatsSpecificNvme' } }
## ##
@ -2796,7 +2796,7 @@
## ##
{ 'enum': 'BlockdevAioOptions', { 'enum': 'BlockdevAioOptions',
'data': [ 'threads', 'native', 'data': [ 'threads', 'native',
{ 'name': 'io_uring', 'if': 'defined(CONFIG_LINUX_IO_URING)' } ] } { 'name': 'io_uring', 'if': 'CONFIG_LINUX_IO_URING' } ] }
## ##
# @BlockdevCacheOptions: # @BlockdevCacheOptions:
@ -2832,12 +2832,12 @@
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs', 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
'gluster', 'gluster',
{'name': 'host_cdrom', 'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' }, {'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
{'name': 'host_device', 'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' }, {'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'http', 'https', 'iscsi', 'http', 'https', 'iscsi',
'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'luks', 'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels',
'preallocate', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'rbd', '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' ] } 'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
## ##
@ -2879,10 +2879,10 @@
'*locking': 'OnOffAuto', '*locking': 'OnOffAuto',
'*aio': 'BlockdevAioOptions', '*aio': 'BlockdevAioOptions',
'*drop-cache': {'type': 'bool', '*drop-cache': {'type': 'bool',
'if': 'defined(CONFIG_LINUX)'}, 'if': 'CONFIG_LINUX'},
'*x-check-cache-dropped': 'bool' }, '*x-check-cache-dropped': 'bool' },
'features': [ { 'name': 'dynamic-auto-read-only', 'features': [ { 'name': 'dynamic-auto-read-only',
'if': 'defined(CONFIG_POSIX)' } ] } 'if': 'CONFIG_POSIX' } ] }
## ##
# @BlockdevOptionsNull: # @BlockdevOptionsNull:
@ -3774,7 +3774,7 @@
# Since: 2.9 # Since: 2.9
## ##
{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ], { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @BlockdevOptionsReplication: # @BlockdevOptionsReplication:
@ -3793,7 +3793,7 @@
'base': 'BlockdevOptionsGenericFormat', 'base': 'BlockdevOptionsGenericFormat',
'data': { 'mode': 'ReplicationMode', 'data': { 'mode': 'ReplicationMode',
'*top-id': 'str' }, '*top-id': 'str' },
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @NFSTransport: # @NFSTransport:
@ -4108,9 +4108,9 @@
'ftps': 'BlockdevOptionsCurlFtps', 'ftps': 'BlockdevOptionsCurlFtps',
'gluster': 'BlockdevOptionsGluster', 'gluster': 'BlockdevOptionsGluster',
'host_cdrom': { 'type': 'BlockdevOptionsFile', 'host_cdrom': { 'type': 'BlockdevOptionsFile',
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' }, 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'host_device': { 'type': 'BlockdevOptionsFile', 'host_device': { 'type': 'BlockdevOptionsFile',
'if': 'defined(HAVE_HOST_BLOCK_DEVICE)' }, 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'http': 'BlockdevOptionsCurlHttp', 'http': 'BlockdevOptionsCurlHttp',
'https': 'BlockdevOptionsCurlHttps', 'https': 'BlockdevOptionsCurlHttps',
'iscsi': 'BlockdevOptionsIscsi', 'iscsi': 'BlockdevOptionsIscsi',
@ -4129,7 +4129,7 @@
'raw': 'BlockdevOptionsRaw', 'raw': 'BlockdevOptionsRaw',
'rbd': 'BlockdevOptionsRbd', 'rbd': 'BlockdevOptionsRbd',
'replication': { 'type': 'BlockdevOptionsReplication', 'replication': { 'type': 'BlockdevOptionsReplication',
'if': 'defined(CONFIG_REPLICATION)' }, 'if': 'CONFIG_REPLICATION' },
'ssh': 'BlockdevOptionsSsh', 'ssh': 'BlockdevOptionsSsh',
'throttle': 'BlockdevOptionsThrottle', 'throttle': 'BlockdevOptionsThrottle',
'vdi': 'BlockdevOptionsGenericFormat', 'vdi': 'BlockdevOptionsGenericFormat',
@ -4307,8 +4307,8 @@
# @size: Size of the virtual disk in bytes # @size: Size of the virtual disk in bytes
# @preallocation: Preallocation mode for the new image (default: off; # @preallocation: Preallocation mode for the new image (default: off;
# allowed values: off, # allowed values: off,
# falloc (if defined CONFIG_POSIX_FALLOCATE), # falloc (if CONFIG_POSIX_FALLOCATE),
# full (if defined CONFIG_POSIX)) # full (if CONFIG_POSIX))
# @nocow: Turn off copy-on-write (valid only on btrfs; default: off) # @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 # @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) # adding an extent size hint (default: 1 MB, since 5.1)
@ -4331,8 +4331,8 @@
# @size: Size of the virtual disk in bytes # @size: Size of the virtual disk in bytes
# @preallocation: Preallocation mode for the new image (default: off; # @preallocation: Preallocation mode for the new image (default: off;
# allowed values: off, # allowed values: off,
# falloc (if defined CONFIG_GLUSTERFS_FALLOCATE), # falloc (if CONFIG_GLUSTERFS_FALLOCATE),
# full (if defined CONFIG_GLUSTERFS_ZEROFILL)) # full (if CONFIG_GLUSTERFS_ZEROFILL))
# #
# Since: 2.12 # Since: 2.12
## ##
@ -4432,7 +4432,7 @@
# Since: 5.1 # Since: 5.1
## ##
{ 'enum': 'Qcow2CompressionType', { 'enum': 'Qcow2CompressionType',
'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } 'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
## ##
# @BlockdevCreateOptionsQcow2: # @BlockdevCreateOptionsQcow2:

View File

@ -168,7 +168,7 @@
'data': { 'mountpoint': 'str', 'data': { 'mountpoint': 'str',
'*growable': 'bool', '*growable': 'bool',
'*allow-other': 'FuseExportAllowOther' }, '*allow-other': 'FuseExportAllowOther' },
'if': 'defined(CONFIG_FUSE)' } 'if': 'CONFIG_FUSE' }
## ##
# @NbdServerAddOptions: # @NbdServerAddOptions:
@ -278,7 +278,7 @@
## ##
{ 'enum': 'BlockExportType', { 'enum': 'BlockExportType',
'data': [ 'nbd', 'vhost-user-blk', 'data': [ 'nbd', 'vhost-user-blk',
{ 'name': 'fuse', 'if': 'defined(CONFIG_FUSE)' } ] } { 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] }
## ##
# @BlockExportOptions: # @BlockExportOptions:
@ -321,7 +321,7 @@
'nbd': 'BlockExportOptionsNbd', 'nbd': 'BlockExportOptionsNbd',
'vhost-user-blk': 'BlockExportOptionsVhostUserBlk', 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk',
'fuse': { 'type': 'BlockExportOptionsFuse', 'fuse': { 'type': 'BlockExportOptionsFuse',
'if': 'defined(CONFIG_FUSE)' } 'if': 'CONFIG_FUSE' }
} } } }
## ##

View File

@ -342,7 +342,7 @@
{ 'struct': 'ChardevSpiceChannel', { 'struct': 'ChardevSpiceChannel',
'data': { 'type': 'str' }, 'data': { 'type': 'str' },
'base': 'ChardevCommon', 'base': 'ChardevCommon',
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @ChardevSpicePort: # @ChardevSpicePort:
@ -356,7 +356,7 @@
{ 'struct': 'ChardevSpicePort', { 'struct': 'ChardevSpicePort',
'data': { 'fqdn': 'str' }, 'data': { 'fqdn': 'str' },
'base': 'ChardevCommon', 'base': 'ChardevCommon',
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @ChardevVC: # @ChardevVC:
@ -405,7 +405,7 @@
'data': { '*mouse': 'bool', 'data': { '*mouse': 'bool',
'*clipboard': 'bool' }, '*clipboard': 'bool' },
'base': 'ChardevCommon', 'base': 'ChardevCommon',
'if': 'defined(CONFIG_SPICE_PROTOCOL)' } 'if': 'CONFIG_SPICE_PROTOCOL' }
## ##
# @ChardevBackend: # @ChardevBackend:
@ -431,11 +431,11 @@
'stdio': 'ChardevStdio', 'stdio': 'ChardevStdio',
'console': 'ChardevCommon', 'console': 'ChardevCommon',
'spicevmc': { 'type': 'ChardevSpiceChannel', 'spicevmc': { 'type': 'ChardevSpiceChannel',
'if': 'defined(CONFIG_SPICE)' }, 'if': 'CONFIG_SPICE' },
'spiceport': { 'type': 'ChardevSpicePort', 'spiceport': { 'type': 'ChardevSpicePort',
'if': 'defined(CONFIG_SPICE)' }, 'if': 'CONFIG_SPICE' },
'qemu-vdagent': { 'type': 'ChardevQemuVDAgent', 'qemu-vdagent': { 'type': 'ChardevQemuVDAgent',
'if': 'defined(CONFIG_SPICE_PROTOCOL)' }, 'if': 'CONFIG_SPICE_PROTOCOL' },
'vc': 'ChardevVC', 'vc': 'ChardevVC',
'ringbuf': 'ChardevRingbuf', 'ringbuf': 'ChardevRingbuf',
# next one is just for compatibility # next one is just for compatibility

View File

@ -89,7 +89,7 @@
## ##
{ 'struct': 'CpuModelBaselineInfo', { 'struct': 'CpuModelBaselineInfo',
'data': { 'model': 'CpuModelInfo' }, 'data': { 'model': 'CpuModelInfo' },
'if': 'defined(TARGET_S390X)' } 'if': 'TARGET_S390X' }
## ##
# @CpuModelCompareInfo: # @CpuModelCompareInfo:
@ -112,7 +112,7 @@
{ 'struct': 'CpuModelCompareInfo', { 'struct': 'CpuModelCompareInfo',
'data': { 'result': 'CpuModelCompareResult', 'data': { 'result': 'CpuModelCompareResult',
'responsible-properties': ['str'] }, 'responsible-properties': ['str'] },
'if': 'defined(TARGET_S390X)' } 'if': 'TARGET_S390X' }
## ##
# @query-cpu-model-comparison: # @query-cpu-model-comparison:
@ -156,7 +156,7 @@
{ 'command': 'query-cpu-model-comparison', { 'command': 'query-cpu-model-comparison',
'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' }, 'data': { 'modela': 'CpuModelInfo', 'modelb': 'CpuModelInfo' },
'returns': 'CpuModelCompareInfo', 'returns': 'CpuModelCompareInfo',
'if': 'defined(TARGET_S390X)' } 'if': 'TARGET_S390X' }
## ##
# @query-cpu-model-baseline: # @query-cpu-model-baseline:
@ -200,7 +200,7 @@
'data': { 'modela': 'CpuModelInfo', 'data': { 'modela': 'CpuModelInfo',
'modelb': 'CpuModelInfo' }, 'modelb': 'CpuModelInfo' },
'returns': 'CpuModelBaselineInfo', 'returns': 'CpuModelBaselineInfo',
'if': 'defined(TARGET_S390X)' } 'if': 'TARGET_S390X' }
## ##
# @CpuModelExpansionInfo: # @CpuModelExpansionInfo:
@ -213,7 +213,9 @@
## ##
{ 'struct': 'CpuModelExpansionInfo', { 'struct': 'CpuModelExpansionInfo',
'data': { 'model': 'CpuModelInfo' }, '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: # @query-cpu-model-expansion:
@ -252,7 +254,9 @@
'data': { 'type': 'CpuModelExpansionType', 'data': { 'type': 'CpuModelExpansionType',
'model': 'CpuModelInfo' }, 'model': 'CpuModelInfo' },
'returns': 'CpuModelExpansionInfo', 'returns': 'CpuModelExpansionInfo',
'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' } 'if': { 'any': [ 'TARGET_S390X',
'TARGET_I386',
'TARGET_ARM' ] } }
## ##
# @CpuDefinitionInfo: # @CpuDefinitionInfo:
@ -316,7 +320,11 @@
'typename': 'str', 'typename': 'str',
'*alias-of' : 'str', '*alias-of' : 'str',
'deprecated' : 'bool' }, '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: # @query-cpu-definitions:
@ -328,4 +336,8 @@
# Since: 1.2 # Since: 1.2
## ##
{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'], { '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' ] } }

View File

@ -533,7 +533,7 @@
## ##
{ 'enum': 'MultiFDCompression', { 'enum': 'MultiFDCompression',
'data': [ 'none', 'zlib', 'data': [ 'none', 'zlib',
{ 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] }
## ##
# @BitmapMigrationBitmapAliasTransform: # @BitmapMigrationBitmapAliasTransform:
@ -1562,7 +1562,7 @@
## ##
{ 'command': 'xen-set-replication', { 'command': 'xen-set-replication',
'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' }, 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @ReplicationStatus: # @ReplicationStatus:
@ -1578,7 +1578,7 @@
## ##
{ 'struct': 'ReplicationStatus', { 'struct': 'ReplicationStatus',
'data': { 'error': 'bool', '*desc': 'str' }, 'data': { 'error': 'bool', '*desc': 'str' },
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @query-xen-replication-status: # @query-xen-replication-status:
@ -1596,7 +1596,7 @@
## ##
{ 'command': 'query-xen-replication-status', { 'command': 'query-xen-replication-status',
'returns': 'ReplicationStatus', 'returns': 'ReplicationStatus',
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @xen-colo-do-checkpoint: # @xen-colo-do-checkpoint:
@ -1613,7 +1613,7 @@
# Since: 2.9 # Since: 2.9
## ##
{ 'command': 'xen-colo-do-checkpoint', { 'command': 'xen-colo-do-checkpoint',
'if': 'defined(CONFIG_REPLICATION)' } 'if': 'CONFIG_REPLICATION' }
## ##
# @COLOStatus: # @COLOStatus:

View File

@ -23,7 +23,17 @@
## ##
{ 'event': 'RTC_CHANGE', { 'event': 'RTC_CHANGE',
'data': { 'offset': 'int' }, '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: # @rtc-reset-reinjection:
@ -42,7 +52,7 @@
# #
## ##
{ 'command': 'rtc-reset-reinjection', { 'command': 'rtc-reset-reinjection',
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
@ -69,7 +79,7 @@
{ 'enum': 'SevState', { 'enum': 'SevState',
'data': ['uninit', 'launch-update', 'launch-secret', 'running', 'data': ['uninit', 'launch-update', 'launch-secret', 'running',
'send-update', 'receive-update' ], 'send-update', 'receive-update' ],
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @SevInfo: # @SevInfo:
@ -101,7 +111,7 @@
'state' : 'SevState', 'state' : 'SevState',
'handle' : 'uint32' 'handle' : 'uint32'
}, },
'if': 'defined(TARGET_I386)' 'if': 'TARGET_I386'
} }
## ##
@ -122,7 +132,7 @@
# #
## ##
{ 'command': 'query-sev', 'returns': 'SevInfo', { 'command': 'query-sev', 'returns': 'SevInfo',
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
@ -136,7 +146,7 @@
# #
## ##
{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'}, { 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'},
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @query-sev-launch-measure: # @query-sev-launch-measure:
@ -154,7 +164,7 @@
# #
## ##
{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo', { 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo',
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
@ -179,7 +189,7 @@
'cert-chain': 'str', 'cert-chain': 'str',
'cbitpos': 'int', 'cbitpos': 'int',
'reduced-phys-bits': 'int'}, 'reduced-phys-bits': 'int'},
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @query-sev-capabilities: # @query-sev-capabilities:
@ -199,7 +209,7 @@
# #
## ##
{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability', { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @sev-inject-launch-secret: # @sev-inject-launch-secret:
@ -217,7 +227,7 @@
## ##
{ 'command': 'sev-inject-launch-secret', { 'command': 'sev-inject-launch-secret',
'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' }, 'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' },
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @dump-skeys: # @dump-skeys:
@ -239,7 +249,7 @@
## ##
{ 'command': 'dump-skeys', { 'command': 'dump-skeys',
'data': { 'filename': 'str' }, 'data': { 'filename': 'str' },
'if': 'defined(TARGET_S390X)' } 'if': 'TARGET_S390X' }
## ##
# @GICCapability: # @GICCapability:
@ -264,7 +274,7 @@
'data': { 'version': 'int', 'data': { 'version': 'int',
'emulated': 'bool', 'emulated': 'bool',
'kernel': 'bool' }, 'kernel': 'bool' },
'if': 'defined(TARGET_ARM)' } 'if': 'TARGET_ARM' }
## ##
# @query-gic-capabilities: # @query-gic-capabilities:
@ -284,7 +294,7 @@
# #
## ##
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'], { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
'if': 'defined(TARGET_ARM)' } 'if': 'TARGET_ARM' }
## ##
@ -300,7 +310,7 @@
## ##
{ 'struct': 'SevAttestationReport', { 'struct': 'SevAttestationReport',
'data': { 'data': 'str'}, 'data': { 'data': 'str'},
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }
## ##
# @query-sev-attestation-report: # @query-sev-attestation-report:
@ -322,4 +332,4 @@
## ##
{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' }, { 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
'returns': 'SevAttestationReport', 'returns': 'SevAttestationReport',
'if': 'defined(TARGET_I386)' } 'if': 'TARGET_I386' }

View File

@ -618,7 +618,7 @@
'data': { '*align': 'size', 'data': { '*align': 'size',
'*discard-data': 'bool', '*discard-data': 'bool',
'mem-path': 'str', 'mem-path': 'str',
'*pmem': { 'type': 'bool', 'if': 'defined(CONFIG_LIBPMEM)' }, '*pmem': { 'type': 'bool', 'if': 'CONFIG_LIBPMEM' },
'*readonly': 'bool' } } '*readonly': 'bool' } }
## ##
@ -782,7 +782,7 @@
'cryptodev-backend', 'cryptodev-backend',
'cryptodev-backend-builtin', 'cryptodev-backend-builtin',
{ 'name': 'cryptodev-vhost-user', { 'name': 'cryptodev-vhost-user',
'if': 'defined(CONFIG_VHOST_CRYPTO)' }, 'if': 'CONFIG_VHOST_CRYPTO' },
'dbus-vmstate', 'dbus-vmstate',
'filter-buffer', 'filter-buffer',
'filter-dump', 'filter-dump',
@ -795,7 +795,7 @@
'iothread', 'iothread',
'memory-backend-file', 'memory-backend-file',
{ 'name': 'memory-backend-memfd', { 'name': 'memory-backend-memfd',
'if': 'defined(CONFIG_LINUX)' }, 'if': 'CONFIG_LINUX' },
'memory-backend-ram', 'memory-backend-ram',
'pef-guest', 'pef-guest',
'pr-manager-helper', 'pr-manager-helper',
@ -840,7 +840,7 @@
'cryptodev-backend': 'CryptodevBackendProperties', 'cryptodev-backend': 'CryptodevBackendProperties',
'cryptodev-backend-builtin': 'CryptodevBackendProperties', 'cryptodev-backend-builtin': 'CryptodevBackendProperties',
'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties', 'cryptodev-vhost-user': { 'type': 'CryptodevVhostUserProperties',
'if': 'defined(CONFIG_VHOST_CRYPTO)' }, 'if': 'CONFIG_VHOST_CRYPTO' },
'dbus-vmstate': 'DBusVMStateProperties', 'dbus-vmstate': 'DBusVMStateProperties',
'filter-buffer': 'FilterBufferProperties', 'filter-buffer': 'FilterBufferProperties',
'filter-dump': 'FilterDumpProperties', 'filter-dump': 'FilterDumpProperties',
@ -853,7 +853,7 @@
'iothread': 'IothreadProperties', 'iothread': 'IothreadProperties',
'memory-backend-file': 'MemoryBackendFileProperties', 'memory-backend-file': 'MemoryBackendFileProperties',
'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties',
'if': 'defined(CONFIG_LINUX)' }, 'if': 'CONFIG_LINUX' },
'memory-backend-ram': 'MemoryBackendProperties', 'memory-backend-ram': 'MemoryBackendProperties',
'pr-manager-helper': 'PrManagerHelperProperties', 'pr-manager-helper': 'PrManagerHelperProperties',
'qtest': 'QtestProperties', 'qtest': 'QtestProperties',

View File

@ -69,7 +69,7 @@
'*ipv4': 'bool', '*ipv4': 'bool',
'*ipv6': 'bool', '*ipv6': 'bool',
'*keep-alive': 'bool', '*keep-alive': 'bool',
'*mptcp': { 'type': 'bool', 'if': 'defined(IPPROTO_MPTCP)' } } } '*mptcp': { 'type': 'bool', 'if': 'IPPROTO_MPTCP' } } }
## ##
# @UnixSocketAddress: # @UnixSocketAddress:
@ -89,8 +89,8 @@
{ 'struct': 'UnixSocketAddress', { 'struct': 'UnixSocketAddress',
'data': { 'data': {
'path': 'str', 'path': 'str',
'*abstract': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' }, '*abstract': { 'type': 'bool', 'if': 'CONFIG_LINUX' },
'*tight': { 'type': 'bool', 'if': 'defined(CONFIG_LINUX)' } } } '*tight': { 'type': 'bool', 'if': 'CONFIG_LINUX' } } }
## ##
# @VsockSocketAddress: # @VsockSocketAddress:

View File

@ -18,7 +18,7 @@
# Since: 1.5 # Since: 1.5
## ##
{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ], { 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ],
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @query-tpm-models: # @query-tpm-models:
@ -36,7 +36,7 @@
# #
## ##
{ 'command': 'query-tpm-models', 'returns': ['TpmModel'], { 'command': 'query-tpm-models', 'returns': ['TpmModel'],
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @TpmType: # @TpmType:
@ -50,7 +50,7 @@
# Since: 1.5 # Since: 1.5
## ##
{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ], { 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ],
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @query-tpm-types: # @query-tpm-types:
@ -68,7 +68,7 @@
# #
## ##
{ 'command': 'query-tpm-types', 'returns': ['TpmType'], { 'command': 'query-tpm-types', 'returns': ['TpmType'],
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @TPMPassthroughOptions: # @TPMPassthroughOptions:
@ -85,7 +85,7 @@
{ 'struct': 'TPMPassthroughOptions', { 'struct': 'TPMPassthroughOptions',
'data': { '*path': 'str', 'data': { '*path': 'str',
'*cancel-path': 'str' }, '*cancel-path': 'str' },
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @TPMEmulatorOptions: # @TPMEmulatorOptions:
@ -97,7 +97,7 @@
# Since: 2.11 # Since: 2.11
## ##
{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' }, { 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @TpmTypeOptions: # @TpmTypeOptions:
@ -112,7 +112,7 @@
{ 'union': 'TpmTypeOptions', { 'union': 'TpmTypeOptions',
'data': { 'passthrough' : 'TPMPassthroughOptions', 'data': { 'passthrough' : 'TPMPassthroughOptions',
'emulator': 'TPMEmulatorOptions' }, 'emulator': 'TPMEmulatorOptions' },
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @TPMInfo: # @TPMInfo:
@ -131,7 +131,7 @@
'data': {'id': 'str', 'data': {'id': 'str',
'model': 'TpmModel', 'model': 'TpmModel',
'options': 'TpmTypeOptions' }, 'options': 'TpmTypeOptions' },
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }
## ##
# @query-tpm: # @query-tpm:
@ -162,4 +162,4 @@
# #
## ##
{ 'command': 'query-tpm', 'returns': ['TPMInfo'], { 'command': 'query-tpm', 'returns': ['TPMInfo'],
'if': 'defined(CONFIG_TPM)' } 'if': 'CONFIG_TPM' }

View File

@ -123,7 +123,7 @@
'data': { 'host': 'str', 'data': { 'host': 'str',
'port': 'str', 'port': 'str',
'family': 'NetworkAddressFamily' }, 'family': 'NetworkAddressFamily' },
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SpiceServerInfo: # @SpiceServerInfo:
@ -137,7 +137,7 @@
{ 'struct': 'SpiceServerInfo', { 'struct': 'SpiceServerInfo',
'base': 'SpiceBasicInfo', 'base': 'SpiceBasicInfo',
'data': { '*auth': 'str' }, 'data': { '*auth': 'str' },
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SpiceChannel: # @SpiceChannel:
@ -163,7 +163,7 @@
'base': 'SpiceBasicInfo', 'base': 'SpiceBasicInfo',
'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int', 'data': {'connection-id': 'int', 'channel-type': 'int', 'channel-id': 'int',
'tls': 'bool'}, 'tls': 'bool'},
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SpiceQueryMouseMode: # @SpiceQueryMouseMode:
@ -183,7 +183,7 @@
## ##
{ 'enum': 'SpiceQueryMouseMode', { 'enum': 'SpiceQueryMouseMode',
'data': [ 'client', 'server', 'unknown' ], 'data': [ 'client', 'server', 'unknown' ],
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SpiceInfo: # @SpiceInfo:
@ -222,7 +222,7 @@
'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int', 'data': {'enabled': 'bool', 'migrated': 'bool', '*host': 'str', '*port': 'int',
'*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str', '*tls-port': 'int', '*auth': 'str', '*compiled-version': 'str',
'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']}, 'mouse-mode': 'SpiceQueryMouseMode', '*channels': ['SpiceChannel']},
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @query-spice: # @query-spice:
@ -268,7 +268,7 @@
# #
## ##
{ 'command': 'query-spice', 'returns': 'SpiceInfo', { 'command': 'query-spice', 'returns': 'SpiceInfo',
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SPICE_CONNECTED: # @SPICE_CONNECTED:
@ -294,7 +294,7 @@
{ 'event': 'SPICE_CONNECTED', { 'event': 'SPICE_CONNECTED',
'data': { 'server': 'SpiceBasicInfo', 'data': { 'server': 'SpiceBasicInfo',
'client': 'SpiceBasicInfo' }, 'client': 'SpiceBasicInfo' },
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SPICE_INITIALIZED: # @SPICE_INITIALIZED:
@ -323,7 +323,7 @@
{ 'event': 'SPICE_INITIALIZED', { 'event': 'SPICE_INITIALIZED',
'data': { 'server': 'SpiceServerInfo', 'data': { 'server': 'SpiceServerInfo',
'client': 'SpiceChannel' }, 'client': 'SpiceChannel' },
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SPICE_DISCONNECTED: # @SPICE_DISCONNECTED:
@ -349,7 +349,7 @@
{ 'event': 'SPICE_DISCONNECTED', { 'event': 'SPICE_DISCONNECTED',
'data': { 'server': 'SpiceBasicInfo', 'data': { 'server': 'SpiceBasicInfo',
'client': 'SpiceBasicInfo' }, 'client': 'SpiceBasicInfo' },
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# @SPICE_MIGRATE_COMPLETED: # @SPICE_MIGRATE_COMPLETED:
@ -365,7 +365,7 @@
# #
## ##
{ 'event': 'SPICE_MIGRATE_COMPLETED', { 'event': 'SPICE_MIGRATE_COMPLETED',
'if': 'defined(CONFIG_SPICE)' } 'if': 'CONFIG_SPICE' }
## ##
# == VNC # == VNC
@ -393,7 +393,7 @@
'service': 'str', 'service': 'str',
'family': 'NetworkAddressFamily', 'family': 'NetworkAddressFamily',
'websocket': 'bool' }, 'websocket': 'bool' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncServerInfo: # @VncServerInfo:
@ -408,7 +408,7 @@
{ 'struct': 'VncServerInfo', { 'struct': 'VncServerInfo',
'base': 'VncBasicInfo', 'base': 'VncBasicInfo',
'data': { '*auth': 'str' }, 'data': { '*auth': 'str' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncClientInfo: # @VncClientInfo:
@ -426,7 +426,7 @@
{ 'struct': 'VncClientInfo', { 'struct': 'VncClientInfo',
'base': 'VncBasicInfo', 'base': 'VncBasicInfo',
'data': { '*x509_dname': 'str', '*sasl_username': 'str' }, 'data': { '*x509_dname': 'str', '*sasl_username': 'str' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncInfo: # @VncInfo:
@ -469,7 +469,7 @@
'data': {'enabled': 'bool', '*host': 'str', 'data': {'enabled': 'bool', '*host': 'str',
'*family': 'NetworkAddressFamily', '*family': 'NetworkAddressFamily',
'*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']}, '*service': 'str', '*auth': 'str', '*clients': ['VncClientInfo']},
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncPrimaryAuth: # @VncPrimaryAuth:
@ -481,7 +481,7 @@
{ 'enum': 'VncPrimaryAuth', { 'enum': 'VncPrimaryAuth',
'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra', 'data': [ 'none', 'vnc', 'ra2', 'ra2ne', 'tight', 'ultra',
'tls', 'vencrypt', 'sasl' ], 'tls', 'vencrypt', 'sasl' ],
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncVencryptSubAuth: # @VncVencryptSubAuth:
@ -496,7 +496,7 @@
'tls-vnc', 'x509-vnc', 'tls-vnc', 'x509-vnc',
'tls-plain', 'x509-plain', 'tls-plain', 'x509-plain',
'tls-sasl', 'x509-sasl' ], 'tls-sasl', 'x509-sasl' ],
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncServerInfo2: # @VncServerInfo2:
@ -514,7 +514,7 @@
'base': 'VncBasicInfo', 'base': 'VncBasicInfo',
'data': { 'auth' : 'VncPrimaryAuth', 'data': { 'auth' : 'VncPrimaryAuth',
'*vencrypt' : 'VncVencryptSubAuth' }, '*vencrypt' : 'VncVencryptSubAuth' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VncInfo2: # @VncInfo2:
@ -547,7 +547,7 @@
'auth' : 'VncPrimaryAuth', 'auth' : 'VncPrimaryAuth',
'*vencrypt' : 'VncVencryptSubAuth', '*vencrypt' : 'VncVencryptSubAuth',
'*display' : 'str' }, '*display' : 'str' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @query-vnc: # @query-vnc:
@ -579,7 +579,7 @@
# #
## ##
{ 'command': 'query-vnc', 'returns': 'VncInfo', { 'command': 'query-vnc', 'returns': 'VncInfo',
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @query-vnc-servers: # @query-vnc-servers:
# #
@ -590,7 +590,7 @@
# Since: 2.3 # Since: 2.3
## ##
{ 'command': 'query-vnc-servers', 'returns': ['VncInfo2'], { 'command': 'query-vnc-servers', 'returns': ['VncInfo2'],
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @change-vnc-password: # @change-vnc-password:
@ -606,7 +606,7 @@
## ##
{ 'command': 'change-vnc-password', { 'command': 'change-vnc-password',
'data': { 'password': 'str' }, 'data': { 'password': 'str' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VNC_CONNECTED: # @VNC_CONNECTED:
@ -636,7 +636,7 @@
{ 'event': 'VNC_CONNECTED', { 'event': 'VNC_CONNECTED',
'data': { 'server': 'VncServerInfo', 'data': { 'server': 'VncServerInfo',
'client': 'VncBasicInfo' }, 'client': 'VncBasicInfo' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VNC_INITIALIZED: # @VNC_INITIALIZED:
@ -664,7 +664,7 @@
{ 'event': 'VNC_INITIALIZED', { 'event': 'VNC_INITIALIZED',
'data': { 'server': 'VncServerInfo', 'data': { 'server': 'VncServerInfo',
'client': 'VncClientInfo' }, 'client': 'VncClientInfo' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# @VNC_DISCONNECTED: # @VNC_DISCONNECTED:
@ -691,7 +691,7 @@
{ 'event': 'VNC_DISCONNECTED', { 'event': 'VNC_DISCONNECTED',
'data': { 'server': 'VncServerInfo', 'data': { 'server': 'VncServerInfo',
'client': 'VncClientInfo' }, 'client': 'VncClientInfo' },
'if': 'defined(CONFIG_VNC)' } 'if': 'CONFIG_VNC' }
## ##
# = Input # = Input
@ -1133,13 +1133,13 @@
'data' : [ 'data' : [
{ 'name': 'default' }, { 'name': 'default' },
{ 'name': 'none' }, { 'name': 'none' },
{ 'name': 'gtk', 'if': 'defined(CONFIG_GTK)' }, { 'name': 'gtk', 'if': 'CONFIG_GTK' },
{ 'name': 'sdl', 'if': 'defined(CONFIG_SDL)' }, { 'name': 'sdl', 'if': 'CONFIG_SDL' },
{ 'name': 'egl-headless', { 'name': 'egl-headless',
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' }, 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } },
{ 'name': 'curses', 'if': 'defined(CONFIG_CURSES)' }, { 'name': 'curses', 'if': 'CONFIG_CURSES' },
{ 'name': 'cocoa', 'if': 'defined(CONFIG_COCOA)' }, { 'name': 'cocoa', 'if': 'CONFIG_COCOA' },
{ 'name': 'spice-app', 'if': 'defined(CONFIG_SPICE)'} ] } { 'name': 'spice-app', 'if': 'CONFIG_SPICE'} ] }
## ##
# @DisplayOptions: # @DisplayOptions:
@ -1164,10 +1164,10 @@
'*gl' : 'DisplayGLMode' }, '*gl' : 'DisplayGLMode' },
'discriminator' : 'type', 'discriminator' : 'type',
'data' : { 'data' : {
'gtk': { 'type': 'DisplayGTK', 'if': 'defined(CONFIG_GTK)' }, 'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' },
'curses': { 'type': 'DisplayCurses', 'if': 'defined(CONFIG_CURSES)' }, 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' },
'egl-headless': { 'type': 'DisplayEGLHeadless', 'egl-headless': { 'type': 'DisplayEGLHeadless',
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' } 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }
} }
} }

View File

@ -1380,7 +1380,7 @@
'data': { 'data': {
'keys': ['str'] 'keys': ['str']
}, },
'if': 'defined(CONFIG_POSIX)' } 'if': 'CONFIG_POSIX' }
## ##
@ -1398,7 +1398,7 @@
{ 'command': 'guest-ssh-get-authorized-keys', { 'command': 'guest-ssh-get-authorized-keys',
'data': { 'username': 'str' }, 'data': { 'username': 'str' },
'returns': 'GuestAuthorizedKeys', 'returns': 'GuestAuthorizedKeys',
'if': 'defined(CONFIG_POSIX)' } 'if': 'CONFIG_POSIX' }
## ##
# @guest-ssh-add-authorized-keys: # @guest-ssh-add-authorized-keys:
@ -1416,7 +1416,7 @@
## ##
{ 'command': 'guest-ssh-add-authorized-keys', { 'command': 'guest-ssh-add-authorized-keys',
'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' }, 'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' },
'if': 'defined(CONFIG_POSIX)' } 'if': 'CONFIG_POSIX' }
## ##
# @guest-ssh-remove-authorized-keys: # @guest-ssh-remove-authorized-keys:
@ -1434,4 +1434,4 @@
## ##
{ 'command': 'guest-ssh-remove-authorized-keys', { 'command': 'guest-ssh-remove-authorized-keys',
'data': { 'username': 'str', 'keys': ['str'] }, 'data': { 'username': 'str', 'keys': ['str'] },
'if': 'defined(CONFIG_POSIX)' } 'if': 'CONFIG_POSIX' }

View File

@ -17,7 +17,6 @@ from typing import (
Dict, Dict,
List, List,
Optional, Optional,
Sequence,
Set, Set,
) )
@ -31,6 +30,7 @@ from .gen import (
from .schema import ( from .schema import (
QAPISchema, QAPISchema,
QAPISchemaFeature, QAPISchemaFeature,
QAPISchemaIfCond,
QAPISchemaObjectType, QAPISchemaObjectType,
QAPISchemaType, QAPISchemaType,
) )
@ -301,7 +301,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
def visit_command(self, def visit_command(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
ret_type: Optional[QAPISchemaType], ret_type: Optional[QAPISchemaType],

View File

@ -12,7 +12,13 @@
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
import re 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. #: 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()) name=c_fname(name).upper())
def gen_if(ifcond: Sequence[str]) -> str: def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
ret = '' if not ifcond:
for ifc in ifcond: return ''
ret += mcgen(''' 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 #if %(cond)s
''', cond=ifc) ''', cond=cond)
return ret
def gen_endif(ifcond: Sequence[str]) -> str: def gen_endif(cond: str) -> str:
ret = '' if not cond:
for ifc in reversed(ifcond): return ''
ret += mcgen(''' return mcgen('''
#endif /* %(cond)s */ #endif /* %(cond)s */
''', cond=ifc) ''', cond=cond)
return ret
def must_match(pattern: str, string: str) -> Match[str]: def must_match(pattern: str, string: str) -> Match[str]:

View File

@ -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. 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 .common import c_enum_const, c_name, mcgen
from .gen import QAPISchemaModularCVisitor, build_params, ifcontext from .gen import QAPISchemaModularCVisitor, build_params, ifcontext
@ -20,6 +20,7 @@ from .schema import (
QAPISchema, QAPISchema,
QAPISchemaEnumMember, QAPISchemaEnumMember,
QAPISchemaFeature, QAPISchemaFeature,
QAPISchemaIfCond,
QAPISchemaObjectType, QAPISchemaObjectType,
) )
from .source import QAPISourceInfo from .source import QAPISourceInfo
@ -227,7 +228,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict);
def visit_event(self, def visit_event(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
boxed: bool) -> None: boxed: bool) -> None:

View File

@ -259,14 +259,9 @@ def check_flags(expr: _JSONObject, info: QAPISourceInfo) -> None:
def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> 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]``. The ``if`` member may be either a ``str`` or a dict.
A ``str`` value will be normalized to ``List[str]``.
:forms:
:sugared: ``Union[str, List[str]]``
:canonical: ``List[str]``
:param expr: The expression containing the ``if`` member to validate. :param expr: The expression containing the ``if`` member to validate.
:param info: QAPI schema source file information. :param info: QAPI schema source file information.
@ -275,31 +270,49 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
:raise QAPISemError: :raise QAPISemError:
When the "if" member fails validation, or when there are no When the "if" member fails validation, or when there are no
non-empty conditions. 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') ifcond = expr.get('if')
if ifcond is None: if ifcond is None:
return return
if isinstance(ifcond, list): _check_if(ifcond)
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))
def normalize_members(members: object) -> None: def normalize_members(members: object) -> None:

View File

@ -18,7 +18,6 @@ from typing import (
Dict, Dict,
Iterator, Iterator,
Optional, Optional,
Sequence,
Tuple, Tuple,
) )
@ -32,6 +31,7 @@ from .common import (
mcgen, mcgen,
) )
from .schema import ( from .schema import (
QAPISchemaIfCond,
QAPISchemaModule, QAPISchemaModule,
QAPISchemaObjectType, QAPISchemaObjectType,
QAPISchemaVisitor, QAPISchemaVisitor,
@ -85,7 +85,7 @@ class QAPIGen:
fp.write(text) 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: if before == after:
return after # suppress empty #if ... #endif 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': if added[0] == '\n':
out += '\n' out += '\n'
added = added[1:] added = added[1:]
out += gen_if(ifcond) out += gen_if(ifcond.cgen())
out += added out += added
out += gen_endif(ifcond) out += gen_endif(ifcond.cgen())
return out return out
@ -127,9 +127,9 @@ def build_params(arg_type: Optional[QAPISchemaObjectType],
class QAPIGenCCode(QAPIGen): class QAPIGenCCode(QAPIGen):
def __init__(self, fname: str): def __init__(self, fname: str):
super().__init__(fname) 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 assert self._start_if is None
self._start_if = (ifcond, self._body, self._preamble) self._start_if = (ifcond, self._body, self._preamble)
@ -187,7 +187,7 @@ class QAPIGenH(QAPIGenC):
@contextmanager @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()`. A with-statement context manager that wraps with `start_if()` / `end_if()`.

View File

@ -15,11 +15,9 @@ from typing import (
Any, Any,
Dict, Dict,
Generic, Generic,
Iterable,
List, List,
Optional, Optional,
Sequence, Sequence,
Tuple,
TypeVar, TypeVar,
Union, Union,
) )
@ -38,6 +36,7 @@ from .schema import (
QAPISchemaEntity, QAPISchemaEntity,
QAPISchemaEnumMember, QAPISchemaEnumMember,
QAPISchemaFeature, QAPISchemaFeature,
QAPISchemaIfCond,
QAPISchemaObjectType, QAPISchemaObjectType,
QAPISchemaObjectTypeMember, QAPISchemaObjectTypeMember,
QAPISchemaType, QAPISchemaType,
@ -91,11 +90,11 @@ class Annotated(Generic[_ValueT]):
""" """
# TODO: Remove after Python 3.7 adds @dataclass: # TODO: Remove after Python 3.7 adds @dataclass:
# pylint: disable=too-few-public-methods # 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): comment: Optional[str] = None):
self.value = value self.value = value
self.comment: Optional[str] = comment self.comment: Optional[str] = comment
self.ifcond: Tuple[str, ...] = tuple(ifcond) self.ifcond = ifcond
def _tree_to_qlit(obj: JSONValue, def _tree_to_qlit(obj: JSONValue,
@ -124,11 +123,11 @@ def _tree_to_qlit(obj: JSONValue,
ret = '' ret = ''
if obj.comment: if obj.comment:
ret += indent(level) + f"/* {obj.comment} */\n" ret += indent(level) + f"/* {obj.comment} */\n"
if obj.ifcond: if obj.ifcond.is_present():
ret += gen_if(obj.ifcond) ret += gen_if(obj.ifcond.cgen())
ret += _tree_to_qlit(obj.value, level) ret += _tree_to_qlit(obj.value, level)
if obj.ifcond: if obj.ifcond.is_present():
ret += '\n' + gen_endif(obj.ifcond) ret += '\n' + gen_endif(obj.ifcond.cgen())
return ret return ret
ret = '' ret = ''
@ -254,7 +253,7 @@ const QLitObject %(c_name)s = %(c_string)s;
return [Annotated(f.name, f.ifcond) for f in features] return [Annotated(f.name, f.ifcond) for f in features]
def _gen_tree(self, name: str, mtype: str, obj: Dict[str, object], def _gen_tree(self, name: str, mtype: str, obj: Dict[str, object],
ifcond: Sequence[str] = (), ifcond: QAPISchemaIfCond = QAPISchemaIfCond(),
features: Sequence[QAPISchemaFeature] = ()) -> None: features: Sequence[QAPISchemaFeature] = ()) -> None:
""" """
Build and append a SchemaInfo object to self._trees. 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}) self._gen_tree(name, 'builtin', {'json-type': json_type})
def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo], def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember], members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None: 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], def visit_array_type(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
element_type: QAPISchemaType) -> None: element_type: QAPISchemaType) -> None:
element = self._use_type(element_type) element = self._use_type(element_type)
self._gen_tree('[' + element + ']', 'array', {'element-type': element}, self._gen_tree('[' + element + ']', 'array', {'element-type': element},
ifcond) ifcond)
def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo], def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> None: variants: Optional[QAPISchemaVariants]) -> None:
@ -336,7 +335,7 @@ const QLitObject %(c_name)s = %(c_string)s;
self._gen_tree(name, 'object', obj, ifcond, features) self._gen_tree(name, 'object', obj, ifcond, features)
def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo], def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None: variants: QAPISchemaVariants) -> None:
self._gen_tree( self._gen_tree(
@ -348,7 +347,7 @@ const QLitObject %(c_name)s = %(c_string)s;
) )
def visit_command(self, name: str, info: Optional[QAPISourceInfo], def visit_command(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
ret_type: Optional[QAPISchemaType], gen: bool, 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) self._gen_tree(name, 'command', obj, ifcond, features)
def visit_event(self, name: str, info: Optional[QAPISourceInfo], def visit_event(self, name: str, info: Optional[QAPISourceInfo],
ifcond: Sequence[str], features: List[QAPISchemaFeature], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature],
arg_type: Optional[QAPISchemaObjectType], arg_type: Optional[QAPISchemaObjectType],
boxed: bool) -> None: boxed: bool) -> None:
assert self._schema is not None assert self._schema is not None

View File

@ -19,12 +19,31 @@ import os
import re import re
from typing import Optional 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 .error import QAPIError, QAPISemError, QAPISourceError
from .expr import check_exprs from .expr import check_exprs
from .parser import QAPISchemaParser 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: class QAPISchemaEntity:
meta: Optional[str] = None meta: Optional[str] = None
@ -42,7 +61,7 @@ class QAPISchemaEntity:
# such place). # such place).
self.info = info self.info = info
self.doc = doc self.doc = doc
self._ifcond = ifcond or [] self._ifcond = ifcond or QAPISchemaIfCond()
self.features = features or [] self.features = features or []
self._checked = False self._checked = False
@ -593,7 +612,7 @@ class QAPISchemaVariants:
self.info, self.info,
"discriminator member '%s' of %s must not be optional" "discriminator member '%s' of %s must not be optional"
% (self._tag_name, base)) % (self._tag_name, base))
if self.tag_member.ifcond: if self.tag_member.ifcond.is_present():
raise QAPISemError( raise QAPISemError(
self.info, self.info,
"discriminator member '%s' of %s must not be conditional" "discriminator member '%s' of %s must not be conditional"
@ -601,7 +620,7 @@ class QAPISchemaVariants:
else: # simple union else: # simple union
assert isinstance(self.tag_member.type, QAPISchemaEnumType) assert isinstance(self.tag_member.type, QAPISchemaEnumType)
assert not self.tag_member.optional 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 if self._tag_name: # flat union
# branches that are not explicitly covered get an empty type # branches that are not explicitly covered get an empty type
cases = {v.name for v in self.variants} cases = {v.name for v in self.variants}
@ -646,7 +665,7 @@ class QAPISchemaMember:
assert isinstance(name, str) assert isinstance(name, str)
self.name = name self.name = name
self.info = info self.info = info
self.ifcond = ifcond or [] self.ifcond = ifcond or QAPISchemaIfCond()
self.defined_in = None self.defined_in = None
def set_defined_in(self, name): def set_defined_in(self, name):
@ -968,11 +987,13 @@ class QAPISchema:
def _make_features(self, features, info): def _make_features(self, features, info):
if features is None: if features is None:
return [] return []
return [QAPISchemaFeature(f['name'], info, f.get('if')) return [QAPISchemaFeature(f['name'], info,
QAPISchemaIfCond(f.get('if')))
for f in features] for f in features]
def _make_enum_members(self, values, info): 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] for v in values]
def _make_implicit_enum_type(self, name, info, ifcond, values): def _make_implicit_enum_type(self, name, info, ifcond, values):
@ -997,18 +1018,18 @@ class QAPISchema:
name = 'q_obj_%s-%s' % (name, role) name = 'q_obj_%s-%s' % (name, role)
typ = self.lookup_entity(name, QAPISchemaObjectType) typ = self.lookup_entity(name, QAPISchemaObjectType)
if typ: if typ:
# The implicit object type has multiple users. This can # The implicit object type has multiple users. This is
# happen only for simple unions' implicit wrapper types. # either a duplicate definition (which will be flagged
# Its ifcond should be the disjunction of its user's # later), or an implicit wrapper type used for multiple
# ifconds. Not implemented. Instead, we always pass the # simple unions. In the latter case, ifcond should be the
# wrapped type's ifcond, which is trivially the same for all # disjunction of its user's ifconds. Not implemented.
# users. It's also necessary for the wrapper to compile. # Instead, we always pass the wrapped type's ifcond, which
# But it's not tight: the disjunction need not imply it. We # is trivially the same for all users. It's also
# may end up compiling useless wrapper types. # 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 # TODO kill simple unions or implement the disjunction
pass
# pylint: disable=protected-access
assert (ifcond or []) == typ._ifcond
else: else:
self._def_entity(QAPISchemaObjectType( self._def_entity(QAPISchemaObjectType(
name, info, None, ifcond, None, None, members, None)) name, info, None, ifcond, None, None, members, None))
@ -1018,7 +1039,7 @@ class QAPISchema:
name = expr['enum'] name = expr['enum']
data = expr['data'] data = expr['data']
prefix = expr.get('prefix') prefix = expr.get('prefix')
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
self._def_entity(QAPISchemaEnumType( self._def_entity(QAPISchemaEnumType(
name, info, doc, ifcond, features, name, info, doc, ifcond, features,
@ -1036,7 +1057,8 @@ class QAPISchema:
self._make_features(features, info)) self._make_features(features, info))
def _make_members(self, data, 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) value.get('features'), info)
for (key, value) in data.items()] for (key, value) in data.items()]
@ -1044,7 +1066,7 @@ class QAPISchema:
name = expr['struct'] name = expr['struct']
base = expr.get('base') base = expr.get('base')
data = expr['data'] data = expr['data']
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
self._def_entity(QAPISchemaObjectType( self._def_entity(QAPISchemaObjectType(
name, info, doc, ifcond, features, base, name, info, doc, ifcond, features, base,
@ -1067,7 +1089,7 @@ class QAPISchema:
name = expr['union'] name = expr['union']
data = expr['data'] data = expr['data']
base = expr.get('base') base = expr.get('base')
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
tag_name = expr.get('discriminator') tag_name = expr.get('discriminator')
tag_member = None tag_member = None
@ -1076,15 +1098,19 @@ class QAPISchema:
name, info, ifcond, name, info, ifcond,
'base', self._make_members(base, info)) 'base', self._make_members(base, info))
if tag_name: if tag_name:
variants = [self._make_variant(key, value['type'], variants = [
value.get('if'), info) self._make_variant(key, value['type'],
for (key, value) in data.items()] QAPISchemaIfCond(value.get('if')),
info)
for (key, value) in data.items()]
members = [] members = []
else: else:
variants = [self._make_simple_variant(key, value['type'], variants = [
value.get('if'), info) self._make_simple_variant(key, value['type'],
for (key, value) in data.items()] QAPISchemaIfCond(value.get('if')),
enum = [{'name': v.name, 'if': v.ifcond} for v in variants] info)
for (key, value) in data.items()]
enum = [{'name': v.name, 'if': v.ifcond.ifcond} for v in variants]
typ = self._make_implicit_enum_type(name, info, ifcond, enum) typ = self._make_implicit_enum_type(name, info, ifcond, enum)
tag_member = QAPISchemaObjectTypeMember('type', info, typ, False) tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
members = [tag_member] members = [tag_member]
@ -1097,11 +1123,13 @@ class QAPISchema:
def _def_alternate_type(self, expr, info, doc): def _def_alternate_type(self, expr, info, doc):
name = expr['alternate'] name = expr['alternate']
data = expr['data'] data = expr['data']
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
variants = [self._make_variant(key, value['type'], value.get('if'), variants = [
info) self._make_variant(key, value['type'],
for (key, value) in data.items()] QAPISchemaIfCond(value.get('if')),
info)
for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False) tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False)
self._def_entity( self._def_entity(
QAPISchemaAlternateType(name, info, doc, ifcond, features, QAPISchemaAlternateType(name, info, doc, ifcond, features,
@ -1118,7 +1146,7 @@ class QAPISchema:
allow_oob = expr.get('allow-oob', False) allow_oob = expr.get('allow-oob', False)
allow_preconfig = expr.get('allow-preconfig', False) allow_preconfig = expr.get('allow-preconfig', False)
coroutine = expr.get('coroutine', False) coroutine = expr.get('coroutine', False)
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
if isinstance(data, OrderedDict): if isinstance(data, OrderedDict):
data = self._make_implicit_object_type( data = self._make_implicit_object_type(
@ -1137,7 +1165,7 @@ class QAPISchema:
name = expr['event'] name = expr['event']
data = expr.get('data') data = expr.get('data')
boxed = expr.get('boxed', False) boxed = expr.get('boxed', False)
ifcond = expr.get('if') ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info) features = self._make_features(expr.get('features'), info)
if isinstance(data, OrderedDict): if isinstance(data, OrderedDict):
data = self._make_implicit_object_type( data = self._make_implicit_object_type(

View File

@ -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. # See the COPYING file in the top-level directory.
""" """
from typing import List, Optional, Sequence from typing import List, Optional
from .common import ( from .common import (
c_enum_const, c_enum_const,
@ -27,6 +27,7 @@ from .schema import (
QAPISchema, QAPISchema,
QAPISchemaEnumMember, QAPISchemaEnumMember,
QAPISchemaFeature, QAPISchemaFeature,
QAPISchemaIfCond,
QAPISchemaObjectType, QAPISchemaObjectType,
QAPISchemaObjectTypeMember, QAPISchemaObjectTypeMember,
QAPISchemaType, QAPISchemaType,
@ -50,13 +51,13 @@ const QEnumLookup %(c_name)s_lookup = {
''', ''',
c_name=c_name(name)) c_name=c_name(name))
for memb in members: for memb in members:
ret += gen_if(memb.ifcond) ret += gen_if(memb.ifcond.cgen())
index = c_enum_const(name, memb.name, prefix) index = c_enum_const(name, memb.name, prefix)
ret += mcgen(''' ret += mcgen('''
[%(index)s] = "%(name)s", [%(index)s] = "%(name)s",
''', ''',
index=index, name=memb.name) index=index, name=memb.name)
ret += gen_endif(memb.ifcond) ret += gen_endif(memb.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
}, },
@ -80,12 +81,12 @@ typedef enum %(c_name)s {
c_name=c_name(name)) c_name=c_name(name))
for memb in enum_members: for memb in enum_members:
ret += gen_if(memb.ifcond) ret += gen_if(memb.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
%(c_enum)s, %(c_enum)s,
''', ''',
c_enum=c_enum_const(name, memb.name, prefix)) c_enum=c_enum_const(name, memb.name, prefix))
ret += gen_endif(memb.ifcond) ret += gen_endif(memb.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
} %(c_name)s; } %(c_name)s;
@ -125,7 +126,7 @@ struct %(c_name)s {
def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str: def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
ret = '' ret = ''
for memb in members: for memb in members:
ret += gen_if(memb.ifcond) ret += gen_if(memb.ifcond.cgen())
if memb.optional: if memb.optional:
ret += mcgen(''' ret += mcgen('''
bool has_%(c_name)s; 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)s %(c_name)s;
''', ''',
c_type=memb.type.c_type(), c_name=c_name(memb.name)) 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 return ret
def gen_object(name: str, ifcond: Sequence[str], def gen_object(name: str, ifcond: QAPISchemaIfCond,
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
variants: Optional[QAPISchemaVariants]) -> str: variants: Optional[QAPISchemaVariants]) -> str:
@ -158,7 +159,7 @@ def gen_object(name: str, ifcond: Sequence[str],
ret += mcgen(''' ret += mcgen('''
''') ''')
ret += gen_if(ifcond) ret += gen_if(ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
struct %(c_name)s { struct %(c_name)s {
''', ''',
@ -192,7 +193,7 @@ struct %(c_name)s {
ret += mcgen(''' ret += mcgen('''
}; };
''') ''')
ret += gen_endif(ifcond) ret += gen_endif(ifcond.cgen())
return ret return ret
@ -219,13 +220,13 @@ def gen_variants(variants: QAPISchemaVariants) -> str:
for var in variants.variants: for var in variants.variants:
if var.type.name == 'q_empty': if var.type.name == 'q_empty':
continue continue
ret += gen_if(var.ifcond) ret += gen_if(var.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
%(c_type)s %(c_name)s; %(c_type)s %(c_name)s;
''', ''',
c_type=var.type.c_unboxed_type(), c_type=var.type.c_unboxed_type(),
c_name=c_name(var.name)) c_name=c_name(var.name))
ret += gen_endif(var.ifcond) ret += gen_endif(var.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
} u; } u;
@ -307,7 +308,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self, def visit_enum_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember], members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None: prefix: Optional[str]) -> None:
@ -318,7 +319,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self, def visit_array_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
element_type: QAPISchemaType) -> None: element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):
self._genh.preamble_add(gen_fwd_object_or_array(name)) self._genh.preamble_add(gen_fwd_object_or_array(name))
@ -328,7 +329,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self, def visit_object_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
@ -351,7 +352,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self, def visit_alternate_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None: variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh): with ifcontext(ifcond, self._genh):

View File

@ -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. See the COPYING file in the top-level directory.
""" """
from typing import List, Optional, Sequence from typing import List, Optional
from .common import ( from .common import (
c_enum_const, c_enum_const,
@ -29,6 +29,7 @@ from .schema import (
QAPISchemaEnumMember, QAPISchemaEnumMember,
QAPISchemaEnumType, QAPISchemaEnumType,
QAPISchemaFeature, QAPISchemaFeature,
QAPISchemaIfCond,
QAPISchemaObjectType, QAPISchemaObjectType,
QAPISchemaObjectTypeMember, QAPISchemaObjectTypeMember,
QAPISchemaType, QAPISchemaType,
@ -78,7 +79,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
for memb in members: for memb in members:
deprecated = 'deprecated' in [f.name for f in memb.features] deprecated = 'deprecated' in [f.name for f in memb.features]
ret += gen_if(memb.ifcond) ret += gen_if(memb.ifcond.cgen())
if memb.optional: if memb.optional:
ret += mcgen(''' ret += mcgen('''
if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) { 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 += mcgen('''
} }
''') ''')
ret += gen_endif(memb.ifcond) ret += gen_endif(memb.ifcond.cgen())
if variants: if variants:
tag_member = variants.tag_member 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: for var in variants.variants:
case_str = c_enum_const(tag_member.type.name, var.name, case_str = c_enum_const(tag_member.type.name, var.name,
tag_member.type.prefix) tag_member.type.prefix)
ret += gen_if(var.ifcond) ret += gen_if(var.ifcond.cgen())
if var.type.name == 'q_empty': if var.type.name == 'q_empty':
# valid variant and nothing to do # valid variant and nothing to do
ret += mcgen(''' ret += mcgen('''
@ -141,7 +142,7 @@ bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
case=case_str, case=case_str,
c_type=var.type.c_name(), c_name=c_name(var.name)) 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(''' ret += mcgen('''
default: default:
abort(); abort();
@ -227,7 +228,7 @@ bool visit_type_%(c_name)s(Visitor *v, const char *name,
c_name=c_name(name)) c_name=c_name(name))
for var in variants.variants: for var in variants.variants:
ret += gen_if(var.ifcond) ret += gen_if(var.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
case %(case)s: case %(case)s:
''', ''',
@ -253,7 +254,7 @@ bool visit_type_%(c_name)s(Visitor *v, const char *name,
ret += mcgen(''' ret += mcgen('''
break; break;
''') ''')
ret += gen_endif(var.ifcond) ret += gen_endif(var.ifcond.cgen())
ret += mcgen(''' ret += mcgen('''
case QTYPE_NONE: case QTYPE_NONE:
@ -352,7 +353,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_enum_type(self, def visit_enum_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
members: List[QAPISchemaEnumMember], members: List[QAPISchemaEnumMember],
prefix: Optional[str]) -> None: prefix: Optional[str]) -> None:
@ -363,7 +364,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_array_type(self, def visit_array_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
element_type: QAPISchemaType) -> None: element_type: QAPISchemaType) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):
self._genh.add(gen_visit_decl(name)) self._genh.add(gen_visit_decl(name))
@ -372,7 +373,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_object_type(self, def visit_object_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
base: Optional[QAPISchemaObjectType], base: Optional[QAPISchemaObjectType],
members: List[QAPISchemaObjectTypeMember], members: List[QAPISchemaObjectTypeMember],
@ -394,7 +395,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def visit_alternate_type(self, def visit_alternate_type(self,
name: str, name: str,
info: Optional[QAPISourceInfo], info: Optional[QAPISourceInfo],
ifcond: Sequence[str], ifcond: QAPISchemaIfCond,
features: List[QAPISchemaFeature], features: List[QAPISchemaFeature],
variants: QAPISchemaVariants) -> None: variants: QAPISchemaVariants) -> None:
with ifcontext(ifcond, self._genh, self._genc): with ifcontext(ifcond, self._genh, self._genc):

View File

@ -1,2 +1,2 @@
alternate-branch-if-invalid.json: In alternate 'Alt': 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

View 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

View File

@ -0,0 +1,3 @@
# check 'if all' is not a list
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': { 'all': 'ALL' } }

View File

View File

@ -1,3 +1,3 @@
# check empty 'if' list # check empty 'if' list
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' }, { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': [] } 'if': { 'all': [] } }

View File

@ -1,2 +1,2 @@
bad-if-empty.json: In struct 'TestIfStruct': 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

View 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'.

View File

@ -0,0 +1,3 @@
# check unknown 'if' dict key
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }

View File

View 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'

View File

@ -0,0 +1,3 @@
# check multiple 'if' keys
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': { 'any': ['ANY'], 'all': ['ALL'] } }

View File

View File

@ -1,2 +1,2 @@
bad-if-list.json: In struct 'TestIfStruct': 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

View File

@ -1,3 +1,3 @@
# check invalid 'if' content # check invalid 'if' content
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' }, { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': ['foo', ' '] } 'if': { 'all': ['foo', ' '] } }

View File

@ -1,2 +1,2 @@
bad-if.json: In struct 'TestIfStruct': 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

View File

@ -1,3 +1,3 @@
# check invalid 'if' type # check invalid 'if' type
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' }, { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
'if': { 'value': 'defined(TEST_IF_STRUCT)' } } 'if': ['TEST_IF_STRUCT'] }

View File

@ -61,16 +61,17 @@
# @two is undocumented # @two is undocumented
## ##
{ 'enum': 'Enum', 'data': { 'enum': 'Enum', 'data':
[ { 'name': 'one', 'if': 'defined(IFONE)' }, 'two' ], [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
'features': [ 'enum-feat' ], 'features': [ 'enum-feat' ],
'if': 'defined(IFCOND)' } 'if': 'IFCOND' }
## ##
# @Base: # @Base:
# @base1: # @base1:
# the first member # the first member
## ##
{ 'struct': 'Base', 'data': { 'base1': 'Enum' } } { 'struct': 'Base', 'data': { 'base1': 'Enum' },
'if': { 'all': ['IFALL1', 'IFALL2'] } }
## ##
# @Variant1: # @Variant1:
@ -86,7 +87,7 @@
'features': [ 'variant1-feat' ], 'features': [ 'variant1-feat' ],
'data': { 'var1': { 'type': 'str', 'data': { 'var1': { 'type': 'str',
'features': [ 'member-feat' ], 'features': [ 'member-feat' ],
'if': 'defined(IFSTR)' } } } 'if': 'IFSTR' } } }
## ##
# @Variant2: # @Variant2:
@ -102,7 +103,9 @@
'features': [ 'union-feat1' ], 'features': [ 'union-feat1' ],
'base': 'Base', 'base': 'Base',
'discriminator': 'base1', 'discriminator': 'base1',
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } } 'data': { 'one': 'Variant1',
'two': { 'type': 'Variant2',
'if': { 'any': ['IFONE', 'IFTWO'] } } } }
## ##
# @SugaredUnion: # @SugaredUnion:
@ -123,7 +126,8 @@
## ##
{ 'alternate': 'Alternate', { 'alternate': 'Alternate',
'features': [ 'alt-feat' ], 'features': [ 'alt-feat' ],
'data': { 'i': 'int', 'b': 'bool' } } 'data': { 'i': 'int', 'b': 'bool' },
'if': { 'not': 'IFNOT' } }
## ##
# == Another subsection # == Another subsection

View File

@ -12,15 +12,16 @@ enum QType
module doc-good.json module doc-good.json
enum Enum enum Enum
member one member one
if ['defined(IFONE)'] if IFONE
member two member two
if ['defined(IFCOND)'] if IFCOND
feature enum-feat feature enum-feat
object Base object Base
member base1: Enum optional=False member base1: Enum optional=False
if OrderedDict([('all', ['IFALL1', 'IFALL2'])])
object Variant1 object Variant1
member var1: str optional=False member var1: str optional=False
if ['defined(IFSTR)'] if IFSTR
feature member-feat feature member-feat
feature variant1-feat feature variant1-feat
object Variant2 object Variant2
@ -29,7 +30,7 @@ object Object
tag base1 tag base1
case one: Variant1 case one: Variant1
case two: Variant2 case two: Variant2
if ['IFTWO'] if OrderedDict([('any', ['IFONE', 'IFTWO'])])
feature union-feat1 feature union-feat1
object q_obj_Variant1-wrapper object q_obj_Variant1-wrapper
member data: Variant1 optional=False member data: Variant1 optional=False
@ -38,18 +39,19 @@ object q_obj_Variant2-wrapper
enum SugaredUnionKind enum SugaredUnionKind
member one member one
member two member two
if ['IFTWO'] if IFTWO
object SugaredUnion object SugaredUnion
member type: SugaredUnionKind optional=False member type: SugaredUnionKind optional=False
tag type tag type
case one: q_obj_Variant1-wrapper case one: q_obj_Variant1-wrapper
case two: q_obj_Variant2-wrapper case two: q_obj_Variant2-wrapper
if ['IFTWO'] if IFTWO
feature union-feat2 feature union-feat2
alternate Alternate alternate Alternate
tag type tag type
case i: int case i: int
case b: bool case b: bool
if OrderedDict([('not', 'IFNOT')])
feature alt-feat feature alt-feat
object q_obj_cmd-arg object q_obj_cmd-arg
member arg1: int optional=False member arg1: int optional=False

View File

@ -43,7 +43,7 @@ Example:
Values Values
~~~~~~ ~~~~~~
"one" (**If: **"defined(IFONE)") "one" (**If: **"IFONE")
The _one_ {and only} The _one_ {and only}
"two" "two"
@ -62,7 +62,7 @@ Features
If If
~~ ~~
"defined(IFCOND)" "IFCOND"
"Base" (Object) "Base" (Object)
@ -76,6 +76,12 @@ Members
the first member the first member
If
~~
"(IFALL1 and IFALL2)"
"Variant1" (Object) "Variant1" (Object)
------------------- -------------------
@ -87,7 +93,7 @@ Another paragraph (but no "var": line)
Members Members
~~~~~~~ ~~~~~~~
"var1": "string" (**If: **"defined(IFSTR)") "var1": "string" (**If: **"IFSTR")
Not documented Not documented
@ -114,7 +120,8 @@ Members
The members of "Base" The members of "Base"
The members of "Variant1" when "base1" is ""one"" 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 Features
~~~~~~~~ ~~~~~~~~
@ -164,6 +171,12 @@ Features
a feature a feature
If
~~
"!IFNOT"
Another subsection Another subsection
================== ==================

View File

@ -1,2 +1,3 @@
enum-if-invalid.json: In enum 'TestIfEnum': 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'.

View File

@ -1,2 +1,2 @@
features-if-invalid.json: In struct 'Stru': 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

View File

@ -1,3 +1,3 @@
{ 'struct': 'FeatureStruct0', { 'struct': 'FeatureStruct0',
'data': { 'foo': 'int' }, 'data': { 'foo': 'int' },
'features': [ { 'if': 'defined(NAMELESS_FEATURES)' } ] } 'features': [ { 'if': 'NAMELESS_FEATURES' } ] }

View File

@ -37,8 +37,11 @@ schemas = [
'bad-data.json', 'bad-data.json',
'bad-ident.json', 'bad-ident.json',
'bad-if.json', 'bad-if.json',
'bad-if-all.json',
'bad-if-empty.json', 'bad-if-empty.json',
'bad-if-empty-list.json', 'bad-if-empty-list.json',
'bad-if-key.json',
'bad-if-keys.json',
'bad-if-list.json', 'bad-if-list.json',
'bad-type-bool.json', 'bad-type-bool.json',
'bad-type-dict.json', 'bad-type-dict.json',

View File

@ -222,44 +222,45 @@
{ 'struct': 'TestIfStruct', 'data': { 'struct': 'TestIfStruct', 'data':
{ 'foo': 'int', { 'foo': 'int',
'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} }, 'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
'if': 'defined(TEST_IF_STRUCT)' } 'if': 'TEST_IF_STRUCT' }
{ 'enum': 'TestIfEnum', 'data': { 'enum': 'TestIfEnum', 'data':
[ 'foo', { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ], [ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
'if': 'defined(TEST_IF_ENUM)' } 'if': 'TEST_IF_ENUM' }
{ 'union': 'TestIfUnion', 'data': { 'union': 'TestIfUnion', 'data':
{ 'foo': 'TestStruct', { 'foo': 'TestStruct',
'bar': { 'type': 'str', 'if': 'defined(TEST_IF_UNION_BAR)'} }, 'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
'if': 'defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)' } 'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
{ 'command': 'test-if-union-cmd', { 'command': 'test-if-union-cmd',
'data': { 'union-cmd-arg': 'TestIfUnion' }, 'data': { 'union-cmd-arg': 'TestIfUnion' },
'if': 'defined(TEST_IF_UNION)' } 'if': 'TEST_IF_UNION' }
{ 'alternate': 'TestIfAlternate', 'data': { 'alternate': 'TestIfAlternate', 'data':
{ 'foo': 'int', { 'foo': 'int',
'bar': { 'type': 'TestStruct', 'if': 'defined(TEST_IF_ALT_BAR)'} }, 'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
'if': 'defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)' } 'if': { 'all': ['TEST_IF_ALT', 'TEST_IF_STRUCT'] } }
{ 'command': 'test-if-alternate-cmd', { 'command': 'test-if-alternate-cmd',
'data': { 'alt-cmd-arg': 'TestIfAlternate' }, 'data': { 'alt-cmd-arg': 'TestIfAlternate' },
'if': 'defined(TEST_IF_ALT)' } 'if': { 'all': ['TEST_IF_ALT',
{'not': 'TEST_IF_NOT_ALT'}] } }
{ 'command': 'test-if-cmd', { 'command': 'test-if-cmd',
'data': { 'data': {
'foo': 'TestIfStruct', 'foo': 'TestIfStruct',
'bar': { 'type': 'TestIfEnum', 'if': 'defined(TEST_IF_CMD_BAR)' } }, 'bar': { 'type': 'TestIfEnum', 'if': 'TEST_IF_CMD_BAR' } },
'returns': 'UserDefThree', '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' } { 'command': 'test-cmd-return-def-three', 'returns': 'UserDefThree' }
{ 'event': 'TEST_IF_EVENT', 'data': { 'event': 'TEST_IF_EVENT', 'data':
{ 'foo': 'TestIfStruct', { 'foo': 'TestIfStruct',
'bar': { 'type': ['TestIfEnum'], 'if': 'defined(TEST_IF_EVT_BAR)' } }, 'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' } 'if': { 'all': ['TEST_IF_EVT', 'TEST_IF_STRUCT'] } }
# test 'features' # test 'features'
@ -281,15 +282,21 @@
{ 'struct': 'CondFeatureStruct1', { 'struct': 'CondFeatureStruct1',
'data': { 'foo': 'int' }, 'data': { 'foo': 'int' },
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'} ] } 'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'} ] }
{ 'struct': 'CondFeatureStruct2', { 'struct': 'CondFeatureStruct2',
'data': { 'foo': 'int' }, 'data': { 'foo': 'int' },
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'}, 'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'},
{ 'name': 'feature2', 'if': 'defined(TEST_IF_FEATURE_2)'} ] } { 'name': 'feature2', 'if': 'TEST_IF_FEATURE_2'} ] }
{ 'struct': 'CondFeatureStruct3', { 'struct': 'CondFeatureStruct3',
'data': { 'foo': 'int' }, 'data': { 'foo': 'int' },
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)', 'features': [ { 'name': 'feature1',
'defined(TEST_IF_COND_2)'] } ] } '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', { 'enum': 'FeatureEnum1',
'data': [ 'eins', 'zwei', 'drei' ], 'data': [ 'eins', 'zwei', 'drei' ],
@ -313,7 +320,8 @@
'*fs4': 'FeatureStruct4', '*fs4': 'FeatureStruct4',
'*cfs1': 'CondFeatureStruct1', '*cfs1': 'CondFeatureStruct1',
'*cfs2': 'CondFeatureStruct2', '*cfs2': 'CondFeatureStruct2',
'*cfs3': 'CondFeatureStruct3' }, '*cfs3': 'CondFeatureStruct3',
'*cfs4': 'CondFeatureStruct4' },
'returns': 'FeatureStruct1', 'returns': 'FeatureStruct1',
'features': [] } 'features': [] }
@ -323,13 +331,14 @@
'features': [ 'feature1', 'feature2' ] } 'features': [ 'feature1', 'feature2' ] }
{ 'command': 'test-command-cond-features1', { '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', { 'command': 'test-command-cond-features2',
'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'}, 'features': [ { 'name': 'feature1', 'if': 'TEST_IF_FEATURE_1'},
{ 'name': 'feature2', 'if': 'defined(TEST_IF_FEATURE_2)'} ] } { 'name': 'feature2', 'if': 'TEST_IF_FEATURE_2'} ] }
{ 'command': 'test-command-cond-features3', { 'command': 'test-command-cond-features3',
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)', 'features': [ { 'name': 'feature1',
'defined(TEST_IF_COND_2)'] } ] } 'if': { 'all': [ 'TEST_IF_COND_1',
'TEST_IF_COND_2'] } } ] }
{ 'event': 'TEST_EVENT_FEATURES0', { 'event': 'TEST_EVENT_FEATURES0',
'data': 'FeatureStruct1' } 'data': 'FeatureStruct1' }

View File

@ -298,65 +298,65 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio
object TestIfStruct object TestIfStruct
member foo: int optional=False member foo: int optional=False
member bar: int optional=False member bar: int optional=False
if ['defined(TEST_IF_STRUCT_BAR)'] if TEST_IF_STRUCT_BAR
if ['defined(TEST_IF_STRUCT)'] if TEST_IF_STRUCT
enum TestIfEnum enum TestIfEnum
member foo member foo
member bar member bar
if ['defined(TEST_IF_ENUM_BAR)'] if TEST_IF_ENUM_BAR
if ['defined(TEST_IF_ENUM)'] if TEST_IF_ENUM
object q_obj_TestStruct-wrapper object q_obj_TestStruct-wrapper
member data: TestStruct optional=False member data: TestStruct optional=False
enum TestIfUnionKind enum TestIfUnionKind
member foo member foo
member bar member bar
if ['defined(TEST_IF_UNION_BAR)'] if TEST_IF_UNION_BAR
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_UNION', 'TEST_IF_STRUCT'])])
object TestIfUnion object TestIfUnion
member type: TestIfUnionKind optional=False member type: TestIfUnionKind optional=False
tag type tag type
case foo: q_obj_TestStruct-wrapper case foo: q_obj_TestStruct-wrapper
case bar: q_obj_str-wrapper case bar: q_obj_str-wrapper
if ['defined(TEST_IF_UNION_BAR)'] if TEST_IF_UNION_BAR
if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_UNION', 'TEST_IF_STRUCT'])])
object q_obj_test-if-union-cmd-arg object q_obj_test-if-union-cmd-arg
member union-cmd-arg: TestIfUnion optional=False 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 command test-if-union-cmd q_obj_test-if-union-cmd-arg -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
if ['defined(TEST_IF_UNION)'] if TEST_IF_UNION
alternate TestIfAlternate alternate TestIfAlternate
tag type tag type
case foo: int case foo: int
case bar: TestStruct case bar: TestStruct
if ['defined(TEST_IF_ALT_BAR)'] if TEST_IF_ALT_BAR
if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_ALT', 'TEST_IF_STRUCT'])])
object q_obj_test-if-alternate-cmd-arg object q_obj_test-if-alternate-cmd-arg
member alt-cmd-arg: TestIfAlternate optional=False 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 command test-if-alternate-cmd q_obj_test-if-alternate-cmd-arg -> None
gen=True success_response=True boxed=False oob=False preconfig=False 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 object q_obj_test-if-cmd-arg
member foo: TestIfStruct optional=False member foo: TestIfStruct optional=False
member bar: TestIfEnum optional=False member bar: TestIfEnum optional=False
if ['defined(TEST_IF_CMD_BAR)'] if TEST_IF_CMD_BAR
if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_CMD', 'TEST_IF_STRUCT'])])
command test-if-cmd q_obj_test-if-cmd-arg -> UserDefThree command test-if-cmd q_obj_test-if-cmd-arg -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False 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 command test-cmd-return-def-three None -> UserDefThree
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
array TestIfEnumList TestIfEnum array TestIfEnumList TestIfEnum
if ['defined(TEST_IF_ENUM)'] if TEST_IF_ENUM
object q_obj_TEST_IF_EVENT-arg object q_obj_TEST_IF_EVENT-arg
member foo: TestIfStruct optional=False member foo: TestIfStruct optional=False
member bar: TestIfEnumList optional=False member bar: TestIfEnumList optional=False
if ['defined(TEST_IF_EVT_BAR)'] if TEST_IF_EVT_BAR
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_EVT', 'TEST_IF_STRUCT'])])
event TEST_IF_EVENT q_obj_TEST_IF_EVENT-arg event TEST_IF_EVENT q_obj_TEST_IF_EVENT-arg
boxed=False boxed=False
if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)'] if OrderedDict([('all', ['TEST_IF_EVT', 'TEST_IF_STRUCT'])])
object FeatureStruct0 object FeatureStruct0
member foo: int optional=False member foo: int optional=False
object FeatureStruct1 object FeatureStruct1
@ -379,17 +379,21 @@ object FeatureStruct4
object CondFeatureStruct1 object CondFeatureStruct1
member foo: int optional=False member foo: int optional=False
feature feature1 feature feature1
if ['defined(TEST_IF_FEATURE_1)'] if TEST_IF_FEATURE_1
object CondFeatureStruct2 object CondFeatureStruct2
member foo: int optional=False member foo: int optional=False
feature feature1 feature feature1
if ['defined(TEST_IF_FEATURE_1)'] if TEST_IF_FEATURE_1
feature feature2 feature feature2
if ['defined(TEST_IF_FEATURE_2)'] if TEST_IF_FEATURE_2
object CondFeatureStruct3 object CondFeatureStruct3
member foo: int optional=False member foo: int optional=False
feature feature1 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 enum FeatureEnum1
member eins member eins
member zwei member zwei
@ -417,6 +421,7 @@ object q_obj_test-features0-arg
member cfs1: CondFeatureStruct1 optional=True member cfs1: CondFeatureStruct1 optional=True
member cfs2: CondFeatureStruct2 optional=True member cfs2: CondFeatureStruct2 optional=True
member cfs3: CondFeatureStruct3 optional=True member cfs3: CondFeatureStruct3 optional=True
member cfs4: CondFeatureStruct4 optional=True
command test-features0 q_obj_test-features0-arg -> FeatureStruct1 command test-features0 q_obj_test-features0-arg -> FeatureStruct1
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
command test-command-features1 None -> None command test-command-features1 None -> None
@ -429,17 +434,17 @@ command test-command-features3 None -> None
command test-command-cond-features1 None -> None command test-command-cond-features1 None -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
feature feature1 feature feature1
if ['defined(TEST_IF_FEATURE_1)'] if TEST_IF_FEATURE_1
command test-command-cond-features2 None -> None command test-command-cond-features2 None -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
feature feature1 feature feature1
if ['defined(TEST_IF_FEATURE_1)'] if TEST_IF_FEATURE_1
feature feature2 feature feature2
if ['defined(TEST_IF_FEATURE_2)'] if TEST_IF_FEATURE_2
command test-command-cond-features3 None -> None command test-command-cond-features3 None -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
feature feature1 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 event TEST_EVENT_FEATURES0 FeatureStruct1
boxed=False boxed=False
event TEST_EVENT_FEATURES1 None event TEST_EVENT_FEATURES1 None

View File

@ -1,3 +1,3 @@
# we reject duplicate events # we reject duplicate events
{ 'event': 'EVENT_A', 'data': { 'myint': 'int' } } { 'event': 'EVENT_A', 'data': { 'myint': 'int' } }
{ 'event': 'EVENT_A', 'data': { 'myint': 'int' } } { 'event': 'EVENT_A', 'data': { 'myint': 'int' }, 'if': 'FOO' }

View File

@ -1,2 +1,2 @@
struct-member-if-invalid.json: In struct 'Stru': 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

View File

@ -94,8 +94,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
@staticmethod @staticmethod
def _print_if(ifcond, indent=4): def _print_if(ifcond, indent=4):
if ifcond: if ifcond.is_present():
print('%sif %s' % (' ' * indent, ifcond)) print('%sif %s' % (' ' * indent, ifcond.ifcond))
@classmethod @classmethod
def _print_features(cls, features, indent=4): def _print_features(cls, features, indent=4):

View File

@ -1,2 +1,2 @@
union-branch-if-invalid.json: In union 'Uni': 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

View File

@ -3,4 +3,4 @@
{ 'struct': 'Stru', 'data': { 'member': 'str' } } { 'struct': 'Stru', 'data': { 'member': 'str' } }
{ 'union': 'Uni', { 'union': 'Uni',
'base': { 'tag': 'Branches' }, 'discriminator': 'tag', 'base': { 'tag': 'Branches' }, 'discriminator': 'tag',
'data': { 'branch1': { 'type': 'Stru', 'if': [''] } } } 'data': { 'branch1': { 'type': 'Stru', 'if': { 'all': [''] } } } }

View File

@ -51,6 +51,7 @@ FeatureStruct1 *qmp_test_features0(bool has_fs0, FeatureStruct0 *fs0,
bool has_cfs1, CondFeatureStruct1 *cfs1, bool has_cfs1, CondFeatureStruct1 *cfs1,
bool has_cfs2, CondFeatureStruct2 *cfs2, bool has_cfs2, CondFeatureStruct2 *cfs2,
bool has_cfs3, CondFeatureStruct3 *cfs3, bool has_cfs3, CondFeatureStruct3 *cfs3,
bool has_cfs4, CondFeatureStruct4 *cfs4,
Error **errp) Error **errp)
{ {
return g_new0(FeatureStruct1, 1); return g_new0(FeatureStruct1, 1);