Commit 32bafa8f authored by Eric Blake's avatar Eric Blake Committed by Markus Armbruster

qapi: Don't special-case simple union wrappers

Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type().  But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:

| struct q_obj_ImageInfoSpecificQCow2_wrapper {
|     ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
|     ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
|     ImageInfoSpecificKind type;
|     union { /* union tag is @type */
|         void *data;
|-        ImageInfoSpecificQCow2 *qcow2;
|-        ImageInfoSpecificVmdk *vmdk;
|+        q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+        q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
|     } u;
| };

Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation).  Using the implicit type
also lets us get rid of the simple_union_type() hack.

Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access.  The generated
qapi-visit.c code is also affected by the layout change:

|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
|     }
|     switch (obj->type) {
|     case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|-        visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+        visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
|         break;
|     case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|-        visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+        visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
|         break;
|     default:
|         abort();
Signed-off-by: 's avatarEric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: 's avatarMarkus Armbruster <armbru@redhat.com>
parent 861877a0
......@@ -567,7 +567,7 @@ static CharDriverState *chr_baum_init(const char *id,
ChardevReturn *ret,
Error **errp)
{
ChardevCommon *common = backend->u.braille;
ChardevCommon *common = backend->u.braille.data;
BaumDriverState *baum;
CharDriverState *chr;
brlapi_handle_t *handle;
......
......@@ -68,7 +68,7 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
ChardevReturn *ret,
Error **errp)
{
ChardevCommon *common = backend->u.msmouse;
ChardevCommon *common = backend->u.msmouse.data;
CharDriverState *chr;
chr = qemu_chr_alloc(common, errp);
......
......@@ -206,13 +206,13 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export,
if (qdict_haskey(options, "path")) {
UnixSocketAddress *q_unix;
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
q_unix = saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
q_unix = saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
q_unix->path = g_strdup(qdict_get_str(options, "path"));
qdict_del(options, "path");
} else {
InetSocketAddress *inet;
saddr->type = SOCKET_ADDRESS_KIND_INET;
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
inet->host = g_strdup(qdict_get_str(options, "host"));
if (!qdict_get_try_str(options, "port")) {
inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
......@@ -321,7 +321,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
error_setg(errp, "TLS only supported over IP sockets");
goto error;
}
hostname = saddr->u.inet->host;
hostname = saddr->u.inet.data->host;
}
/* establish TCP connection, return error if it fails
......
......@@ -2800,15 +2800,15 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
*spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
.u.qcow2 = g_new(ImageInfoSpecificQCow2, 1),
.u.qcow2.data = g_new(ImageInfoSpecificQCow2, 1),
};
if (s->qcow_version == 2) {
*spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
*spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
.compat = g_strdup("0.10"),
.refcount_bits = s->refcount_bits,
};
} else if (s->qcow_version == 3) {
*spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
*spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
.compat = g_strdup("1.1"),
.lazy_refcounts = s->compatible_features &
QCOW2_COMPAT_LAZY_REFCOUNTS,
......
......@@ -2203,18 +2203,18 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
*spec_info = (ImageInfoSpecific){
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
{
.vmdk = g_new0(ImageInfoSpecificVmdk, 1),
.u = {
.vmdk.data = g_new0(ImageInfoSpecificVmdk, 1),
},
};
*spec_info->u.vmdk = (ImageInfoSpecificVmdk) {
*spec_info->u.vmdk.data = (ImageInfoSpecificVmdk) {
.create_type = g_strdup(s->create_type),
.cid = s->cid,
.parent_cid = s->parent_cid,
};
next = &spec_info->u.vmdk->extents;
next = &spec_info->u.vmdk.data->extents;
for (i = 0; i < s->num_extents; i++) {
*next = g_new0(ImageInfoList, 1);
(*next)->value = vmdk_get_extent_info(&s->extents[i]);
......
......@@ -1247,7 +1247,7 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
};
TransactionAction action = {
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
.u.blockdev_snapshot_sync = &snapshot,
.u.blockdev_snapshot_sync.data = &snapshot,
};
blockdev_do_action(&action, errp);
}
......@@ -1261,7 +1261,7 @@ void qmp_blockdev_snapshot(const char *node, const char *overlay,
};
TransactionAction action = {
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
.u.blockdev_snapshot = &snapshot_data,
.u.blockdev_snapshot.data = &snapshot_data,
};
blockdev_do_action(&action, errp);
}
......@@ -1276,7 +1276,7 @@ void qmp_blockdev_snapshot_internal_sync(const char *device,
};
TransactionAction action = {
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
.u.blockdev_snapshot_internal_sync = &snapshot,
.u.blockdev_snapshot_internal_sync.data = &snapshot,
};
blockdev_do_action(&action, errp);
}
......@@ -1515,7 +1515,7 @@ static void internal_snapshot_prepare(BlkActionState *common,
g_assert(common->action->type ==
TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC);
internal = common->action->u.blockdev_snapshot_internal_sync;
internal = common->action->u.blockdev_snapshot_internal_sync.data;
state = DO_UPCAST(InternalSnapshotState, common, common);
/* 1. parse input */
......@@ -1665,7 +1665,7 @@ static void external_snapshot_prepare(BlkActionState *common,
switch (action->type) {
case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
{
BlockdevSnapshot *s = action->u.blockdev_snapshot;
BlockdevSnapshot *s = action->u.blockdev_snapshot.data;
device = s->node;
node_name = s->node;
new_image_file = NULL;
......@@ -1674,7 +1674,7 @@ static void external_snapshot_prepare(BlkActionState *common,
break;
case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
{
BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync;
BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;
device = s->has_device ? s->device : NULL;
node_name = s->has_node_name ? s->node_name : NULL;
new_image_file = s->snapshot_file;
......@@ -1723,7 +1723,7 @@ static void external_snapshot_prepare(BlkActionState *common,
}
if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync;
BlockdevSnapshotSync *s = action->u.blockdev_snapshot_sync.data;
const char *format = s->has_format ? s->format : "qcow2";
enum NewImageMode mode;
const char *snapshot_node_name =
......@@ -1861,7 +1861,7 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
Error *local_err = NULL;
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
backup = common->action->u.drive_backup;
backup = common->action->u.drive_backup.data;
blk = blk_by_name(backup->device);
if (!blk) {
......@@ -1943,7 +1943,7 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
Error *local_err = NULL;
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
backup = common->action->u.blockdev_backup;
backup = common->action->u.blockdev_backup.data;
blk = blk_by_name(backup->device);
if (!blk) {
......@@ -2029,7 +2029,7 @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
return;
}
action = common->action->u.block_dirty_bitmap_add;
action = common->action->u.block_dirty_bitmap_add.data;
/* AIO context taken and released within qmp_block_dirty_bitmap_add */
qmp_block_dirty_bitmap_add(action->node, action->name,
action->has_granularity, action->granularity,
......@@ -2048,7 +2048,7 @@ static void block_dirty_bitmap_add_abort(BlkActionState *common)
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
common, common);
action = common->action->u.block_dirty_bitmap_add;
action = common->action->u.block_dirty_bitmap_add.data;
/* Should not be able to fail: IF the bitmap was added via .prepare(),
* then the node reference and bitmap name must have been valid.
*/
......@@ -2068,7 +2068,7 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
return;
}
action = common->action->u.block_dirty_bitmap_clear;
action = common->action->u.block_dirty_bitmap_clear.data;
state->bitmap = block_dirty_bitmap_lookup(action->node,
action->name,
&state->bs,
......
......@@ -857,7 +857,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
switch (ti->options->type) {
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
tpo = ti->options->u.passthrough;
tpo = ti->options->u.passthrough.data;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
tpo->has_path ? tpo->path : "",
......@@ -1753,14 +1753,14 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
goto err_out;
}
keylist->value->type = KEY_VALUE_KIND_NUMBER;
keylist->value->u.number = value;
keylist->value->u.number.data = value;
} else {
int idx = index_from_key(keys, keyname_len);
if (idx == Q_KEY_CODE__MAX) {
goto err_out;
}
keylist->value->type = KEY_VALUE_KIND_QCODE;
keylist->value->u.qcode = idx;
keylist->value->u.qcode.data = idx;
}
if (!separator) {
......@@ -1977,7 +1977,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
if (value) {
switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
di = value->u.dimm;
di = value->u.dimm.data;
monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
MemoryDeviceInfoKind_lookup[value->type],
......
......@@ -845,7 +845,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
InputKeyEvent *key;
assert(evt->type == INPUT_EVENT_KIND_KEY);
key = evt->u.key;
key = evt->u.key.data;
qcode = qemu_input_key_value_to_qcode(key->key);
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
key->down);
......
......@@ -124,7 +124,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
switch (evt->type) {
case INPUT_EVENT_KIND_REL:
move = evt->u.rel;
move = evt->u.rel.data;
if (move->axis == INPUT_AXIS_X) {
e->xdx += move->value;
} else if (move->axis == INPUT_AXIS_Y) {
......@@ -133,7 +133,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
break;
case INPUT_EVENT_KIND_ABS:
move = evt->u.abs;
move = evt->u.abs.data;
if (move->axis == INPUT_AXIS_X) {
e->xdx = move->value;
} else if (move->axis == INPUT_AXIS_Y) {
......@@ -142,7 +142,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
break;
case INPUT_EVENT_KIND_BTN:
btn = evt->u.btn;
btn = evt->u.btn.data;
if (btn->down) {
e->buttons_state |= bmap[btn->button];
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
......@@ -228,7 +228,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
HIDState *hs = (HIDState *)dev;
int scancodes[3], i, count;
int slot;
InputKeyEvent *key = evt->u.key;
InputKeyEvent *key = evt->u.key.data;
count = qemu_input_key_value_to_scancode(key->key,
key->down,
......
......@@ -182,7 +182,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
{
PS2KbdState *s = (PS2KbdState *)dev;
int scancodes[3], i, count;
InputKeyEvent *key = evt->u.key;
InputKeyEvent *key = evt->u.key.data;
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
count = qemu_input_key_value_to_scancode(key->key,
......@@ -399,7 +399,7 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
switch (evt->type) {
case INPUT_EVENT_KIND_REL:
move = evt->u.rel;
move = evt->u.rel.data;
if (move->axis == INPUT_AXIS_X) {
s->mouse_dx += move->value;
} else if (move->axis == INPUT_AXIS_Y) {
......@@ -408,7 +408,7 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
break;
case INPUT_EVENT_KIND_BTN:
btn = evt->u.btn;
btn = evt->u.btn.data;
if (btn->down) {
s->mouse_buttons |= bmap[btn->button];
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
......
......@@ -197,7 +197,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
switch (evt->type) {
case INPUT_EVENT_KIND_KEY:
key = evt->u.key;
key = evt->u.key.data;
qcode = qemu_input_key_value_to_qcode(key->key);
if (qcode && keymap_qcode[qcode]) {
event.type = cpu_to_le16(EV_KEY);
......@@ -212,7 +212,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
}
break;
case INPUT_EVENT_KIND_BTN:
btn = evt->u.btn;
btn = evt->u.btn.data;
if (keymap_button[btn->button]) {
event.type = cpu_to_le16(EV_KEY);
event.code = cpu_to_le16(keymap_button[btn->button]);
......@@ -227,14 +227,14 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
}
break;
case INPUT_EVENT_KIND_REL:
move = evt->u.rel;
move = evt->u.rel.data;
event.type = cpu_to_le16(EV_REL);
event.code = cpu_to_le16(axismap_rel[move->axis]);
event.value = cpu_to_le32(move->value);
virtio_input_send(vinput, &event);
break;
case INPUT_EVENT_KIND_ABS:
move = evt->u.abs;
move = evt->u.abs.data;
event.type = cpu_to_le16(EV_ABS);
event.code = cpu_to_le16(axismap_abs[move->axis]);
event.value = cpu_to_le32(move->value);
......
......@@ -180,7 +180,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
NULL);
di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
info->u.dimm = di;
info->u.dimm.data = di;
elem->value = info;
elem->next = NULL;
**prev = elem;
......
......@@ -189,7 +189,7 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
DumpNetClient *dnc;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_DUMP);
dump = opts->u.dump;
dump = opts->u.dump.data;
assert(peer);
......
......@@ -288,7 +288,7 @@ int net_init_hubport(const NetClientOptions *opts, const char *name,
assert(opts->type == NET_CLIENT_OPTIONS_KIND_HUBPORT);
assert(!peer);
hubport = opts->u.hubport;
hubport = opts->u.hubport.data;
net_hub_add_port(hubport->hubid, name);
return 0;
......
......@@ -546,7 +546,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
s->header_mismatch = false;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_L2TPV3);
l2tpv3 = opts->u.l2tpv3;
l2tpv3 = opts->u.l2tpv3.data;
if (l2tpv3->has_ipv6 && l2tpv3->ipv6) {
s->ipv6 = l2tpv3->ipv6;
......
......@@ -893,7 +893,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
const NetLegacyNicOptions *nic;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_NIC);
nic = opts->u.nic;
nic = opts->u.nic.data;
idx = nic_get_free_idx();
if (idx == -1 || nb_nics >= MAX_NICS) {
......@@ -1025,7 +1025,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
/* Do not add to a vlan if it's a nic with a netdev= parameter. */
if (opts->type != NET_CLIENT_OPTIONS_KIND_NIC ||
!opts->u.nic->has_netdev) {
!opts->u.nic.data->has_netdev) {
peer = net_hub_add_port(net->has_vlan ? net->vlan : 0, NULL);
}
}
......
......@@ -420,7 +420,7 @@ static NetClientInfo net_netmap_info = {
int net_init_netmap(const NetClientOptions *opts,
const char *name, NetClientState *peer, Error **errp)
{
const NetdevNetmapOptions *netmap_opts = opts->u.netmap;
const NetdevNetmapOptions *netmap_opts = opts->u.netmap.data;
struct nm_desc *nmd;
NetClientState *nc;
Error *err = NULL;
......
......@@ -814,7 +814,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name,
const char **dnssearch;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER);
user = opts->u.user;
user = opts->u.user.data;
vnet = user->has_net ? g_strdup(user->net) :
user->has_ip ? g_strdup_printf("%s/24", user->ip) :
......
......@@ -704,7 +704,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name,
const NetdevSocketOptions *sock;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_SOCKET);
sock = opts->u.socket;
sock = opts->u.socket.data;
if (sock->has_fd + sock->has_listen + sock->has_connect + sock->has_mcast +
sock->has_udp != 1) {
......
......@@ -795,7 +795,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
const NetdevTapOptions *tap;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
tap = opts->u.tap;
tap = opts->u.tap.data;
if (!tap->has_ifname) {
error_report("tap: no interface name");
......
......@@ -565,7 +565,7 @@ int net_init_bridge(const NetClientOptions *opts, const char *name,
int fd, vnet_hdr;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
bridge = opts->u.bridge;
bridge = opts->u.bridge.data;
helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
br = bridge->has_br ? bridge->br : DEFAULT_BRIDGE_INTERFACE;
......@@ -728,7 +728,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
char ifname[128];
assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
tap = opts->u.tap;
tap = opts->u.tap.data;
queues = tap->has_queues ? tap->queues : 1;
vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
......
......@@ -116,7 +116,7 @@ int net_init_vde(const NetClientOptions *opts, const char *name,
const NetdevVdeOptions *vde;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VDE);
vde = opts->u.vde;
vde = opts->u.vde.data;
/* missing optional values have been initialized to "all bits zero" */
if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group,
......
......@@ -306,7 +306,7 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
CharDriverState *chr;
assert(opts->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
vhost_user_opts = opts->u.vhost_user;
vhost_user_opts = opts->u.vhost_user.data;
chr = net_vhost_parse_chardev(vhost_user_opts, errp);
if (!chr) {
......
......@@ -228,7 +228,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
switch (object->type) {
case NUMA_OPTIONS_KIND_NODE:
numa_node_parse(object->u.node, opts, &err);
numa_node_parse(object->u.node.data, opts, &err);
if (err) {
goto error;
}
......@@ -482,7 +482,7 @@ static void numa_stat_memory_devices(uint64_t node_mem[])
if (value) {
switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
node_mem[value->u.dimm->node] += value->u.dimm->size;
node_mem[value->u.dimm.data->node] += value->u.dimm.data->size;
break;
default:
break;
......
This diff is collapsed.
......@@ -377,12 +377,12 @@ static SocketAddress *nbd_build_socket_address(const char *sockpath,
saddr = g_new0(SocketAddress, 1);
if (sockpath) {
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
saddr->u.q_unix->path = g_strdup(sockpath);
saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
saddr->u.q_unix.data->path = g_strdup(sockpath);
} else {
InetSocketAddress *inet;
saddr->type = SOCKET_ADDRESS_KIND_INET;
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
inet->host = g_strdup(bindto);
if (port) {
inet->port = g_strdup(port);
......
......@@ -54,16 +54,16 @@ void replay_save_input_event(InputEvent *evt)
switch (evt->type) {
case INPUT_EVENT_KIND_KEY:
key = evt->u.key;
key = evt->u.key.data;
replay_put_dword(key->key->type);
switch (key->key->type) {
case KEY_VALUE_KIND_NUMBER:
replay_put_qword(key->key->u.number);
replay_put_qword(key->key->u.number.data);
replay_put_byte(key->down);
break;
case KEY_VALUE_KIND_QCODE:
replay_put_dword(key->key->u.qcode);
replay_put_dword(key->key->u.qcode.data);
replay_put_byte(key->down);
break;
case KEY_VALUE_KIND__MAX:
......@@ -72,17 +72,17 @@ void replay_save_input_event(InputEvent *evt)
}
break;
case INPUT_EVENT_KIND_BTN:
btn = evt->u.btn;
btn = evt->u.btn.data;
replay_put_dword(btn->button);
replay_put_byte(btn->down);
break;
case INPUT_EVENT_KIND_REL:
move = evt->u.rel;
move = evt->u.rel.data;
replay_put_dword(move->axis);
replay_put_qword(move->value);
break;
case INPUT_EVENT_KIND_ABS:
move = evt->u.abs;
move = evt->u.abs.data;
replay_put_dword(move->axis);
replay_put_qword(move->value);
break;
......@@ -105,17 +105,17 @@ InputEvent *replay_read_input_event(void)
evt.type = replay_get_dword();
switch (evt.type) {
case INPUT_EVENT_KIND_KEY:
evt.u.key = &key;
evt.u.key->key->type = replay_get_dword();
evt.u.key.data = &key;
evt.u.key.data->key->type = replay_get_dword();
switch (evt.u.key->key->type) {
switch (evt.u.key.data->key->type) {
case KEY_VALUE_KIND_NUMBER:
evt.u.key->key->u.number = replay_get_qword();
evt.u.key->down = replay_get_byte();
evt.u.key.data->key->u.number.data = replay_get_qword();
evt.u.key.data->down = replay_get_byte();
break;
case KEY_VALUE_KIND_QCODE:
evt.u.key->key->u.qcode = (QKeyCode)replay_get_dword();
evt.u.key->down = replay_get_byte();
evt.u.key.data->key->u.qcode.data = (QKeyCode)replay_get_dword();
evt.u.key.data->down = replay_get_byte();
break;
case KEY_VALUE_KIND__MAX:
/* keep gcc happy */
......@@ -123,19 +123,19 @@ InputEvent *replay_read_input_event(void)
}
break;
case INPUT_EVENT_KIND_BTN:
evt.u.btn = &btn;
evt.u.btn->button = (InputButton)replay_get_dword();
evt.u.btn->down = replay_get_byte();
evt.u.btn.data = &btn;
evt.u.btn.data->button = (InputButton)replay_get_dword();
evt.u.btn.data->down = replay_get_byte();
break;
case INPUT_EVENT_KIND_REL:
evt.u.rel = &rel;
evt.u.rel->axis = (InputAxis)replay_get_dword();
evt.u.rel->value = replay_get_qword();
evt.u.rel.data = &rel;
evt.u.rel.data->axis = (InputAxis)replay_get_dword();
evt.u.rel.data->value = replay_get_qword();
break;
case INPUT_EVENT_KIND_ABS:
evt.u.abs = &abs;
evt.u.abs->axis = (InputAxis)replay_get_dword();
evt.u.abs->value = replay_get_qword();
evt.u.abs.data = &abs;
evt.u.abs.data->axis = (InputAxis)replay_get_dword();
evt.u.abs.data->value = replay_get_qword();
break;
case INPUT_EVENT_KIND__MAX:
/* keep gcc happy */
......
......@@ -121,16 +121,10 @@ def gen_variants(variants):
c_name=c_name(variants.tag_member.name))
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
simple_union_type = var.simple_union_type()
if simple_union_type:
typ = simple_union_type.c_type()
else:
typ = var.type.c_unboxed_type()
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
c_type=typ,
c_type=var.type.c_unboxed_type(),
c_name=c_name(var.name))
ret += mcgen('''
......
......@@ -77,29 +77,15 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
c_name=c_name(variants.tag_member.name))
for var in variants.variants:
# TODO ugly special case for simple union
simple_union_type = var.simple_union_type()
ret += mcgen('''
case %(case)s:
visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err);
break;
''',
case=c_enum_const(variants.tag_member.type.name,
var.name,
variants.tag_member.type.prefix))
if simple_union_type:
ret += mcgen('''
visit_type_%(c_type)s(v, "data", &obj->u.%(c_name)s, &err);
''',
c_type=simple_union_type.c_name(),
c_name=c_name(var.name))
else:
ret += mcgen('''
visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err);
''',
c_type=var.type.c_name(),
c_name=c_name(var.name))
ret += mcgen('''
break;
''')
variants.tag_member.type.prefix),
c_type=var.type.c_name(), c_name=c_name(var.name))
ret += mcgen('''
default:
......
......@@ -1115,16 +1115,6 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
def __init__(self, name, typ):
QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
# This function exists to support ugly simple union special cases
# TODO get rid of them, and drop the function
def simple_union_type(self):
if (self.type.is_implicit() and
isinstance(self.type, QAPISchemaObjectType)):
assert len(self.type.members) == 1
assert not self.type.variants
return self.type.members[0].type
return None
class QAPISchemaAlternateType(QAPISchemaType):
def __init__(self, name, info, variants):
......
......@@ -305,9 +305,10 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
ChardevReturn *ret,
Error **errp)
{
const char *type = backend->u.spicevmc->type;
ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
const char *type = spicevmc->type;
const char **psubtype = spice_server_char_device_recognized_subtypes();
ChardevCommon *common = qapi_ChardevSpiceChannel_base(backend->u.spicevmc);
ChardevCommon *common = qapi_ChardevSpiceChannel_base(spicevmc);
for (; *psubtype != NULL; ++psubtype) {
if (strcmp(type, *psubtype) == 0) {
......@@ -329,8 +330,9 @@ static CharDriverState *qemu_chr_open_spice_port(const char *id,
ChardevReturn *ret,
Error **errp)
{
const char *name = backend->u.spiceport->fqdn;
ChardevCommon *common = qapi_ChardevSpicePort_base(backend->u.spiceport);
ChardevSpicePort *spiceport = backend->u.spiceport.data;
const char *name = spiceport->fqdn;
ChardevCommon *common = qapi_ChardevSpicePort_base(spiceport);
CharDriverState *chr;
SpiceCharDriver *s;
......@@ -372,7 +374,7 @@ static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend,
error_setg(errp, "chardev: spice channel: no name given");
return;
}
spicevmc = backend->u.spicevmc = g_new0(ChardevSpiceChannel, 1);
spicevmc = backend->u.spicevmc.data = g_new0(ChardevSpiceChannel, 1);
qemu_chr_parse_common(opts, qapi_ChardevSpiceChannel_base(spicevmc));
spicevmc->type = g_strdup(name);
}
......@@ -387,7 +389,7 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
error_setg(errp, "chardev: spice port: no name given");
return;