qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qapi: Permit alternates with just one branch

A union or alternate without branches makes no sense and doesn't work:
it can't be instantiated. A union or alternate with just one branch
works, but is degenerate. We accept the former, but reject the
latter. Weird. docs/devel/qapi-code-gen.txt doesn't mention the
difference. It claims an alternate definition is "is similar to a
simple union type".

Permit degenerate alternates to make them consistent with unions.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20190913201349.24332-10-armbru@redhat.com>

+12 -10
+2 -4
scripts/qapi/common.py
··· 920 920 members = expr['data'] 921 921 types_seen = {} 922 922 923 - # Check every branch; require at least two branches 924 - if len(members) < 2: 923 + if len(members) == 0: 925 924 raise QAPISemError(info, 926 - "Alternate '%s' should have at least two branches " 927 - "in 'data'" % name) 925 + "Alternate '%s' cannot have empty 'data'" % name) 928 926 for (key, value) in members.items(): 929 927 check_name(info, "Member of alternate '%s'" % name, key) 930 928 check_known_keys(info,
+1 -1
tests/qapi-schema/alternate-empty.err
··· 1 - tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' should have at least two branches in 'data' 1 + tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' cannot have empty 'data'
+2 -2
tests/qapi-schema/alternate-empty.json
··· 1 - # alternates must list at least two types to be useful 2 - { 'alternate': 'Alt', 'data': { 'i': 'int' } } 1 + # alternates cannot be empty 2 + { 'alternate': 'Alt', 'data': { } }
+3 -1
tests/qapi-schema/qapi-schema-test.json
··· 186 186 187 187 # test that we correctly compile downstream extensions, as well as munge 188 188 # ticklish names 189 + # also test union and alternate with just one branch 189 190 { 'enum': '__org.qemu_x-Enum', 'data': [ '__org.qemu_x-value' ] } 190 191 { 'struct': '__org.qemu_x-Base', 191 192 'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } } 192 193 { 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base', 193 194 'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } } 194 195 { 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } } 196 + { 'alternate': '__org.qemu_x-Alt1', 'data': { '__org.qemu_x-branch': 'str' } } 195 197 { 'struct': '__org.qemu_x-Struct2', 196 198 'data': { 'array': ['__org.qemu_x-Union1'] } } 197 199 { 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base', 198 200 'discriminator': '__org.qemu_x-member1', 199 201 'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } } 200 202 { 'alternate': '__org.qemu_x-Alt', 201 - 'data': { '__org.qemu_x-branch': 'str', 'b': '__org.qemu_x-Base' } } 203 + 'data': { '__org.qemu_x-branch': '__org.qemu_x-Base' } } 202 204 { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' } 203 205 { 'command': '__org.qemu_x-command', 204 206 'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
+4 -2
tests/qapi-schema/qapi-schema-test.out
··· 274 274 member type: __org.qemu_x-Union1Kind optional=False 275 275 tag type 276 276 case __org.qemu_x-branch: q_obj_str-wrapper 277 + alternate __org.qemu_x-Alt1 278 + tag type 279 + case __org.qemu_x-branch: str 277 280 array __org.qemu_x-Union1List __org.qemu_x-Union1 278 281 object __org.qemu_x-Struct2 279 282 member array: __org.qemu_x-Union1List optional=False ··· 283 286 case __org.qemu_x-value: __org.qemu_x-Struct2 284 287 alternate __org.qemu_x-Alt 285 288 tag type 286 - case __org.qemu_x-branch: str 287 - case b: __org.qemu_x-Base 289 + case __org.qemu_x-branch: __org.qemu_x-Base 288 290 event __ORG.QEMU_X-EVENT __org.qemu_x-Struct 289 291 boxed=False 290 292 array __org.qemu_x-EnumList __org.qemu_x-Enum