QAPI patches for 2015-12-17
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWcmVVAAoJEDhwtADrkYZTgLwP/2xkMCMhqvepE/wVM7MNygn8 F1KuOd+9Qtt9mhr1MZlBmP1FRMhgIxQ3Ue0HHDTkPfKIem5titibk7YkVYXVDdYC xavxwfLlk7f3PlrzPrF19RnWRGUl5QZ0n914ZFNo0pbT+S9yVFkKMtXvcCHsP/RE f069rFIvJhzGa6gbL+FUkE4SO1SGzV/0xBDgrkUpoezrb23YA4EQKMKFRjPZkraH 0rY3YNrAsKmHzMQlbkWhuhJ0LBoUoAJHle2ZYrk+cT1Gvn7TMH+6RPddwDNNXJrL guAHFdHKljnLqqcbBbcUydoWAMo0YqBbtme+E4GxcSbZiyz/M69eJ46Fyovge/mU pSxRAZChVl3fEACFYsAz42chip4exWHOLvOkODT+CYfVfAeVO5/pNtPi5Y77tJHo KKpDAsB/5XUkCRL9orhpo/g7noix1WUmZLFUPOgL6FWb6D6IHkZwX9f86BoFgvW0 E30rRaSF4l1tATF723AEYKFG41a10iLCkaojy5s+jFPNP77qdvHoHQqtUSjAJyNz bpdEOKt/SLvr4rEYkGf1IJ4Pwvf5nS1yPpahY17dYHwNnHh/ngWCAy18A1to+ACg rNiOw17mJkIe3vBydiy3X7xAq7DPrA39cpRAHoSij1tqPm6mNrpx89WqtfbLWMtY y7k/agDt/WWtUdC/cYmC =X75u -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-12-17' into staging QAPI patches for 2015-12-17 # gpg: Signature made Thu 17 Dec 2015 07:33:41 GMT using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-qapi-2015-12-17: (40 commits) qapi: Detect base class loops qapi: Move duplicate collision checks to schema check() qapi: Enforce (or whitelist) case conventions on qapi members qapi: Track enum values by QAPISchemaMember, not string qapi: Prepare new QAPISchemaMember base class qapi: Shorter visits of optional fields qapi: Simplify visits of optional fields qapi: Fix alternates that accept 'number' but not 'int' qapi: Inline _make_implicit_tag() qapi-types: Drop unnedeed ._fwdefn qapi: Simplify visiting of alternate types qapi: Convert QType into QAPI built-in enum type qobject: Rename qtype_code to QType qobject: Simplify QObject qapi: Change munging of CamelCase enum values qapi: Add alias for ErrorClass cpu: Convert CpuInfo into flat union qapi: Remove obsolete tests for MAX collision qapi: Don't let implicit enum MAX member collide qapi: Tighten the regex on valid names ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c1a5f950cd
2
block.c
2
block.c
|
@ -2851,7 +2851,7 @@ ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
|
||||
{
|
||||
if (!bs || !bs->drv || !bs->drv->bdrv_debug_event) {
|
||||
return;
|
||||
|
|
|
@ -36,7 +36,7 @@ typedef struct BDRVBlkdebugState {
|
|||
int state;
|
||||
int new_state;
|
||||
|
||||
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
|
||||
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX];
|
||||
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
|
||||
QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs;
|
||||
} BDRVBlkdebugState;
|
||||
|
@ -64,7 +64,7 @@ enum {
|
|||
};
|
||||
|
||||
typedef struct BlkdebugRule {
|
||||
BlkDebugEvent event;
|
||||
BlkdebugEvent event;
|
||||
int action;
|
||||
int state;
|
||||
union {
|
||||
|
@ -143,69 +143,12 @@ static QemuOptsList *config_groups[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static const char *event_names[BLKDBG_EVENT_MAX] = {
|
||||
[BLKDBG_L1_UPDATE] = "l1_update",
|
||||
[BLKDBG_L1_GROW_ALLOC_TABLE] = "l1_grow.alloc_table",
|
||||
[BLKDBG_L1_GROW_WRITE_TABLE] = "l1_grow.write_table",
|
||||
[BLKDBG_L1_GROW_ACTIVATE_TABLE] = "l1_grow.activate_table",
|
||||
|
||||
[BLKDBG_L2_LOAD] = "l2_load",
|
||||
[BLKDBG_L2_UPDATE] = "l2_update",
|
||||
[BLKDBG_L2_UPDATE_COMPRESSED] = "l2_update_compressed",
|
||||
[BLKDBG_L2_ALLOC_COW_READ] = "l2_alloc.cow_read",
|
||||
[BLKDBG_L2_ALLOC_WRITE] = "l2_alloc.write",
|
||||
|
||||
[BLKDBG_READ_AIO] = "read_aio",
|
||||
[BLKDBG_READ_BACKING_AIO] = "read_backing_aio",
|
||||
[BLKDBG_READ_COMPRESSED] = "read_compressed",
|
||||
|
||||
[BLKDBG_WRITE_AIO] = "write_aio",
|
||||
[BLKDBG_WRITE_COMPRESSED] = "write_compressed",
|
||||
|
||||
[BLKDBG_VMSTATE_LOAD] = "vmstate_load",
|
||||
[BLKDBG_VMSTATE_SAVE] = "vmstate_save",
|
||||
|
||||
[BLKDBG_COW_READ] = "cow_read",
|
||||
[BLKDBG_COW_WRITE] = "cow_write",
|
||||
|
||||
[BLKDBG_REFTABLE_LOAD] = "reftable_load",
|
||||
[BLKDBG_REFTABLE_GROW] = "reftable_grow",
|
||||
[BLKDBG_REFTABLE_UPDATE] = "reftable_update",
|
||||
|
||||
[BLKDBG_REFBLOCK_LOAD] = "refblock_load",
|
||||
[BLKDBG_REFBLOCK_UPDATE] = "refblock_update",
|
||||
[BLKDBG_REFBLOCK_UPDATE_PART] = "refblock_update_part",
|
||||
[BLKDBG_REFBLOCK_ALLOC] = "refblock_alloc",
|
||||
[BLKDBG_REFBLOCK_ALLOC_HOOKUP] = "refblock_alloc.hookup",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE] = "refblock_alloc.write",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS] = "refblock_alloc.write_blocks",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE] = "refblock_alloc.write_table",
|
||||
[BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE] = "refblock_alloc.switch_table",
|
||||
|
||||
[BLKDBG_CLUSTER_ALLOC] = "cluster_alloc",
|
||||
[BLKDBG_CLUSTER_ALLOC_BYTES] = "cluster_alloc_bytes",
|
||||
[BLKDBG_CLUSTER_FREE] = "cluster_free",
|
||||
|
||||
[BLKDBG_FLUSH_TO_OS] = "flush_to_os",
|
||||
[BLKDBG_FLUSH_TO_DISK] = "flush_to_disk",
|
||||
|
||||
[BLKDBG_PWRITEV_RMW_HEAD] = "pwritev_rmw.head",
|
||||
[BLKDBG_PWRITEV_RMW_AFTER_HEAD] = "pwritev_rmw.after_head",
|
||||
[BLKDBG_PWRITEV_RMW_TAIL] = "pwritev_rmw.tail",
|
||||
[BLKDBG_PWRITEV_RMW_AFTER_TAIL] = "pwritev_rmw.after_tail",
|
||||
[BLKDBG_PWRITEV] = "pwritev",
|
||||
[BLKDBG_PWRITEV_ZERO] = "pwritev_zero",
|
||||
[BLKDBG_PWRITEV_DONE] = "pwritev_done",
|
||||
|
||||
[BLKDBG_EMPTY_IMAGE_PREPARE] = "empty_image_prepare",
|
||||
};
|
||||
|
||||
static int get_event_by_name(const char *name, BlkDebugEvent *event)
|
||||
static int get_event_by_name(const char *name, BlkdebugEvent *event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
if (!strcmp(event_names[i], name)) {
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
if (!strcmp(BlkdebugEvent_lookup[i], name)) {
|
||||
*event = i;
|
||||
return 0;
|
||||
}
|
||||
|
@ -224,7 +167,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
|||
struct add_rule_data *d = opaque;
|
||||
BDRVBlkdebugState *s = d->s;
|
||||
const char* event_name;
|
||||
BlkDebugEvent event;
|
||||
BlkdebugEvent event;
|
||||
struct BlkdebugRule *rule;
|
||||
|
||||
/* Find the right event for the rule */
|
||||
|
@ -564,7 +507,7 @@ static void blkdebug_close(BlockDriverState *bs)
|
|||
BlkdebugRule *rule, *next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
|
||||
remove_rule(rule);
|
||||
}
|
||||
|
@ -627,13 +570,13 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
|
|||
return injected;
|
||||
}
|
||||
|
||||
static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
|
||||
static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule, *next;
|
||||
bool injected;
|
||||
|
||||
assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
|
||||
assert((int)event >= 0 && event < BLKDBG__MAX);
|
||||
|
||||
injected = false;
|
||||
s->new_state = s->state;
|
||||
|
@ -648,7 +591,7 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
|
|||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule;
|
||||
BlkDebugEvent blkdebug_event;
|
||||
BlkdebugEvent blkdebug_event;
|
||||
|
||||
if (get_event_by_name(event, &blkdebug_event) < 0) {
|
||||
return -ENOENT;
|
||||
|
@ -690,7 +633,7 @@ static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs,
|
|||
BlkdebugRule *rule, *next;
|
||||
int i, ret = -ENOENT;
|
||||
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
|
||||
if (rule->action == ACTION_SUSPEND &&
|
||||
!strcmp(rule->options.suspend.tag, tag)) {
|
||||
|
|
|
@ -61,7 +61,7 @@ typedef struct ParallelsHeader {
|
|||
typedef enum ParallelsPreallocMode {
|
||||
PRL_PREALLOC_MODE_FALLOCATE = 0,
|
||||
PRL_PREALLOC_MODE_TRUNCATE = 1,
|
||||
PRL_PREALLOC_MODE_MAX = 2,
|
||||
PRL_PREALLOC_MODE__MAX = 2,
|
||||
} ParallelsPreallocMode;
|
||||
|
||||
static const char *prealloc_mode_lookup[] = {
|
||||
|
@ -660,7 +660,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
|||
s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
|
||||
buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
|
||||
s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
|
||||
PRL_PREALLOC_MODE_MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
|
||||
PRL_PREALLOC_MODE__MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
|
||||
g_free(buf);
|
||||
if (local_err != NULL) {
|
||||
goto fail_options;
|
||||
|
|
|
@ -588,7 +588,7 @@ static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
|
|||
int i = 0;
|
||||
|
||||
for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
|
||||
qtype_code type = qobject_type(entry->value);
|
||||
QType type = qobject_type(entry->value);
|
||||
bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
|
||||
const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
|
||||
|
||||
|
@ -606,7 +606,7 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
|
|||
const QDictEntry *entry;
|
||||
|
||||
for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
|
||||
qtype_code type = qobject_type(entry->value);
|
||||
QType type = qobject_type(entry->value);
|
||||
bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
|
||||
const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
|
||||
char key[strlen(entry->key) + 1];
|
||||
|
|
|
@ -2269,7 +2269,7 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||
DEFAULT_CLUSTER_SIZE);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
|
|
|
@ -847,7 +847,7 @@ static int parse_read_pattern(const char *opt)
|
|||
return QUORUM_READ_PATTERN_QUORUM;
|
||||
}
|
||||
|
||||
for (i = 0; i < QUORUM_READ_PATTERN_MAX; i++) {
|
||||
for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
|
||||
if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -1636,7 +1636,7 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||
nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
g_free(buf);
|
||||
if (local_err) {
|
||||
|
|
|
@ -454,7 +454,7 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
|
|||
*detect_zeroes =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
qemu_opt_get(opts, "detect-zeroes"),
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_error);
|
||||
if (local_error) {
|
||||
|
|
31
cpus.c
31
cpus.c
|
@ -1558,22 +1558,29 @@ CpuInfoList *qmp_query_cpus(Error **errp)
|
|||
info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
|
||||
info->value->thread_id = cpu->thread_id;
|
||||
#if defined(TARGET_I386)
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->eip + env->segs[R_CS].base;
|
||||
info->value->arch = CPU_INFO_ARCH_X86;
|
||||
info->value->u.x86 = g_new0(CpuInfoX86, 1);
|
||||
info->value->u.x86->pc = env->eip + env->segs[R_CS].base;
|
||||
#elif defined(TARGET_PPC)
|
||||
info->value->has_nip = true;
|
||||
info->value->nip = env->nip;
|
||||
info->value->arch = CPU_INFO_ARCH_PPC;
|
||||
info->value->u.ppc = g_new0(CpuInfoPPC, 1);
|
||||
info->value->u.ppc->nip = env->nip;
|
||||
#elif defined(TARGET_SPARC)
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->pc;
|
||||
info->value->has_npc = true;
|
||||
info->value->npc = env->npc;
|
||||
info->value->arch = CPU_INFO_ARCH_SPARC;
|
||||
info->value->u.sparc = g_new0(CpuInfoSPARC, 1);
|
||||
info->value->u.sparc->pc = env->pc;
|
||||
info->value->u.sparc->npc = env->npc;
|
||||
#elif defined(TARGET_MIPS)
|
||||
info->value->has_PC = true;
|
||||
info->value->PC = env->active_tc.PC;
|
||||
info->value->arch = CPU_INFO_ARCH_MIPS;
|
||||
info->value->u.mips = g_new0(CpuInfoMIPS, 1);
|
||||
info->value->u.mips->PC = env->active_tc.PC;
|
||||
#elif defined(TARGET_TRICORE)
|
||||
info->value->has_PC = true;
|
||||
info->value->PC = env->PC;
|
||||
info->value->arch = CPU_INFO_ARCH_TRICORE;
|
||||
info->value->u.tricore = g_new0(CpuInfoTricore, 1);
|
||||
info->value->u.tricore->PC = env->PC;
|
||||
#else
|
||||
info->value->arch = CPU_INFO_ARCH_OTHER;
|
||||
info->value->u.other = g_new0(CpuInfoOther, 1);
|
||||
#endif
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Block I/O error injection using blkdebug
|
||||
----------------------------------------
|
||||
Copyright (C) 2014 Red Hat Inc
|
||||
Copyright (C) 2014-2015 Red Hat Inc
|
||||
|
||||
This work is licensed under the terms of the GNU GPL, version 2 or later. See
|
||||
the COPYING file in the top-level directory.
|
||||
|
@ -92,8 +92,9 @@ The core events are:
|
|||
|
||||
flush_to_disk - flush the host block device's disk cache
|
||||
|
||||
See block/blkdebug.c:event_names[] for the full list of events. You may need
|
||||
to grep block driver source code to understand the meaning of specific events.
|
||||
See qapi/block-core.json:BlkdebugEvent for the full list of events.
|
||||
You may need to grep block driver source code to understand the
|
||||
meaning of specific events.
|
||||
|
||||
State transitions
|
||||
-----------------
|
||||
|
|
|
@ -118,17 +118,17 @@ tracking optional fields.
|
|||
|
||||
Any name (command, event, type, field, or enum value) beginning with
|
||||
"x-" is marked experimental, and may be withdrawn or changed
|
||||
incompatibly in a future release. Downstream vendors may add
|
||||
extensions; such extensions should begin with a prefix matching
|
||||
"__RFQDN_" (for the reverse-fully-qualified-domain-name of the
|
||||
vendor), even if the rest of the name uses dash (example:
|
||||
__com.redhat_drive-mirror). Other than downstream extensions (with
|
||||
leading underscore and the use of dots), all names should begin with a
|
||||
letter, and contain only ASCII letters, digits, dash, and underscore.
|
||||
Names beginning with 'q_' are reserved for the generator: QMP names
|
||||
that resemble C keywords or other problematic strings will be munged
|
||||
in C to use this prefix. For example, a field named "default" in
|
||||
qapi becomes "q_default" in the generated C code.
|
||||
incompatibly in a future release. All names must begin with a letter,
|
||||
and contain only ASCII letters, digits, dash, and underscore. There
|
||||
are two exceptions: enum values may start with a digit, and any
|
||||
extensions added by downstream vendors should start with a prefix
|
||||
matching "__RFQDN_" (for the reverse-fully-qualified-domain-name of
|
||||
the vendor), even if the rest of the name uses dash (example:
|
||||
__com.redhat_drive-mirror). Names beginning with 'q_' are reserved
|
||||
for the generator: QMP names that resemble C keywords or other
|
||||
problematic strings will be munged in C to use this prefix. For
|
||||
example, a field named "default" in qapi becomes "q_default" in the
|
||||
generated C code.
|
||||
|
||||
In the rest of this document, usage lines are given for each
|
||||
expression type, with literal strings written in lower case and
|
||||
|
@ -160,6 +160,7 @@ The following types are predefined, and map to C as follows:
|
|||
accepts size suffixes
|
||||
bool bool JSON true or false
|
||||
any QObject * any JSON value
|
||||
QType QType JSON string matching enum QType values
|
||||
|
||||
|
||||
=== Includes ===
|
||||
|
@ -383,9 +384,6 @@ where each branch of the union names a QAPI type. For example:
|
|||
'data': { 'definition': 'BlockdevOptions',
|
||||
'reference': 'str' } }
|
||||
|
||||
Just like for a simple union, an implicit C enum 'NameKind' is created
|
||||
to enumerate the branches for the alternate 'Name'.
|
||||
|
||||
Unlike a union, the discriminator string is never passed on the wire
|
||||
for the Client JSON Protocol. Instead, the value's JSON type serves
|
||||
as an implicit discriminator, which in turn means that an alternate
|
||||
|
@ -1053,7 +1051,7 @@ Example:
|
|||
|
||||
const char *const example_QAPIEvent_lookup[] = {
|
||||
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
|
||||
[EXAMPLE_QAPI_EVENT_MAX] = NULL,
|
||||
[EXAMPLE_QAPI_EVENT__MAX] = NULL,
|
||||
};
|
||||
$ cat qapi-generated/example-qapi-event.h
|
||||
[Uninteresting stuff omitted...]
|
||||
|
@ -1070,7 +1068,7 @@ Example:
|
|||
|
||||
typedef enum example_QAPIEvent {
|
||||
EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
|
||||
EXAMPLE_QAPI_EVENT_MAX = 1,
|
||||
EXAMPLE_QAPI_EVENT__MAX = 1,
|
||||
} example_QAPIEvent;
|
||||
|
||||
extern const char *const example_QAPIEvent_lookup[];
|
||||
|
|
44
hmp.c
44
hmp.c
|
@ -311,17 +311,25 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
|
|||
|
||||
monitor_printf(mon, "%c CPU #%" PRId64 ":", active, cpu->value->CPU);
|
||||
|
||||
if (cpu->value->has_pc) {
|
||||
monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->pc);
|
||||
}
|
||||
if (cpu->value->has_nip) {
|
||||
monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->nip);
|
||||
}
|
||||
if (cpu->value->has_npc) {
|
||||
monitor_printf(mon, " npc=0x%016" PRIx64, cpu->value->npc);
|
||||
}
|
||||
if (cpu->value->has_PC) {
|
||||
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->PC);
|
||||
switch (cpu->value->arch) {
|
||||
case CPU_INFO_ARCH_X86:
|
||||
monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->u.x86->pc);
|
||||
break;
|
||||
case CPU_INFO_ARCH_PPC:
|
||||
monitor_printf(mon, " nip=0x%016" PRIx64, cpu->value->u.ppc->nip);
|
||||
break;
|
||||
case CPU_INFO_ARCH_SPARC:
|
||||
monitor_printf(mon, " pc=0x%016" PRIx64, cpu->value->u.sparc->pc);
|
||||
monitor_printf(mon, " npc=0x%016" PRIx64, cpu->value->u.sparc->npc);
|
||||
break;
|
||||
case CPU_INFO_ARCH_MIPS:
|
||||
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.mips->PC);
|
||||
break;
|
||||
case CPU_INFO_ARCH_TRICORE:
|
||||
monitor_printf(mon, " PC=0x%016" PRIx64, cpu->value->u.tricore->PC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cpu->value->halted) {
|
||||
|
@ -855,7 +863,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
|||
tpo->has_cancel_path ? ",cancel-path=" : "",
|
||||
tpo->has_cancel_path ? tpo->cancel_path : "");
|
||||
break;
|
||||
case TPM_TYPE_OPTIONS_KIND_MAX:
|
||||
case TPM_TYPE_OPTIONS_KIND__MAX:
|
||||
break;
|
||||
}
|
||||
monitor_printf(mon, "\n");
|
||||
|
@ -1203,7 +1211,7 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
|||
MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
|
||||
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
||||
if (strcmp(cap, MigrationCapability_lookup[i]) == 0) {
|
||||
caps->value = g_malloc0(sizeof(*caps->value));
|
||||
caps->value->capability = i;
|
||||
|
@ -1214,7 +1222,7 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
|||
}
|
||||
}
|
||||
|
||||
if (i == MIGRATION_CAPABILITY_MAX) {
|
||||
if (i == MIGRATION_CAPABILITY__MAX) {
|
||||
error_setg(&err, QERR_INVALID_PARAMETER, cap);
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1247,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
|||
bool has_x_cpu_throttle_increment = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MIGRATION_PARAMETER_MAX; i++) {
|
||||
for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
|
||||
if (strcmp(param, MigrationParameter_lookup[i]) == 0) {
|
||||
switch (i) {
|
||||
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
|
||||
|
@ -1268,7 +1276,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
|||
}
|
||||
}
|
||||
|
||||
if (i == MIGRATION_PARAMETER_MAX) {
|
||||
if (i == MIGRATION_PARAMETER__MAX) {
|
||||
error_setg(&err, QERR_INVALID_PARAMETER, param);
|
||||
}
|
||||
|
||||
|
@ -1368,7 +1376,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
|||
if (read_only) {
|
||||
read_only_mode =
|
||||
qapi_enum_parse(BlockdevChangeReadOnlyMode_lookup,
|
||||
read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_MAX,
|
||||
read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE__MAX,
|
||||
BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
|
||||
if (err) {
|
||||
hmp_handle_error(mon, &err);
|
||||
|
@ -1771,7 +1779,7 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
|
|||
keylist->value->u.number = value;
|
||||
} else {
|
||||
int idx = index_from_key(keyname_buf);
|
||||
if (idx == Q_KEY_CODE_MAX) {
|
||||
if (idx == Q_KEY_CODE__MAX) {
|
||||
goto err_out;
|
||||
}
|
||||
keylist->value->type = KEY_VALUE_KIND_QCODE;
|
||||
|
|
|
@ -714,7 +714,7 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
|
|||
return &d->mmio;
|
||||
}
|
||||
|
||||
static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = {
|
||||
static const uint8_t qcode_to_keycode[Q_KEY_CODE__MAX] = {
|
||||
[Q_KEY_CODE_SHIFT] = 99,
|
||||
[Q_KEY_CODE_SHIFT_R] = 110,
|
||||
[Q_KEY_CODE_ALT] = 19,
|
||||
|
|
|
@ -225,7 +225,7 @@ static void pc_init1(MachineState *machine,
|
|||
|
||||
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
|
||||
|
||||
assert(pcms->vmport != ON_OFF_AUTO_MAX);
|
||||
assert(pcms->vmport != ON_OFF_AUTO__MAX);
|
||||
if (pcms->vmport == ON_OFF_AUTO_AUTO) {
|
||||
pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ static void pc_q35_init(MachineState *machine)
|
|||
|
||||
pc_register_ferr_irq(gsi[13]);
|
||||
|
||||
assert(pcms->vmport != ON_OFF_AUTO_MAX);
|
||||
assert(pcms->vmport != ON_OFF_AUTO__MAX);
|
||||
if (pcms->vmport == ON_OFF_AUTO_AUTO) {
|
||||
pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ void hid_set_next_idle(HIDState *hs)
|
|||
static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
static const int bmap[INPUT_BUTTON_MAX] = {
|
||||
static const int bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = 0x01,
|
||||
[INPUT_BUTTON_RIGHT] = 0x02,
|
||||
[INPUT_BUTTON_MIDDLE] = 0x04,
|
||||
|
@ -139,9 +139,9 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
|
|||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->u.btn->down) {
|
||||
e->buttons_state |= bmap[evt->u.btn->button];
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEELUP) {
|
||||
e->dz--;
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEELDOWN) {
|
||||
e->dz++;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -382,7 +382,7 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
|
|||
static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
static const int bmap[INPUT_BUTTON_MAX] = {
|
||||
static const int bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
|
@ -405,9 +405,9 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
|||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->u.btn->down) {
|
||||
s->mouse_buttons |= bmap[evt->u.btn->button];
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEELUP) {
|
||||
s->mouse_dz--;
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEELDOWN) {
|
||||
s->mouse_dz++;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
static const unsigned int keymap_qcode[Q_KEY_CODE_MAX] = {
|
||||
static const unsigned int keymap_qcode[Q_KEY_CODE__MAX] = {
|
||||
[Q_KEY_CODE_ESC] = KEY_ESC,
|
||||
[Q_KEY_CODE_1] = KEY_1,
|
||||
[Q_KEY_CODE_2] = KEY_2,
|
||||
|
@ -138,20 +138,20 @@ static const unsigned int keymap_qcode[Q_KEY_CODE_MAX] = {
|
|||
[Q_KEY_CODE_MENU] = KEY_MENU,
|
||||
};
|
||||
|
||||
static const unsigned int keymap_button[INPUT_BUTTON_MAX] = {
|
||||
static const unsigned int keymap_button[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = BTN_LEFT,
|
||||
[INPUT_BUTTON_RIGHT] = BTN_RIGHT,
|
||||
[INPUT_BUTTON_MIDDLE] = BTN_MIDDLE,
|
||||
[INPUT_BUTTON_WHEEL_UP] = BTN_GEAR_UP,
|
||||
[INPUT_BUTTON_WHEEL_DOWN] = BTN_GEAR_DOWN,
|
||||
[INPUT_BUTTON_WHEELUP] = BTN_GEAR_UP,
|
||||
[INPUT_BUTTON_WHEELDOWN] = BTN_GEAR_DOWN,
|
||||
};
|
||||
|
||||
static const unsigned int axismap_rel[INPUT_AXIS_MAX] = {
|
||||
static const unsigned int axismap_rel[INPUT_AXIS__MAX] = {
|
||||
[INPUT_AXIS_X] = REL_X,
|
||||
[INPUT_AXIS_Y] = REL_Y,
|
||||
};
|
||||
|
||||
static const unsigned int axismap_abs[INPUT_AXIS_MAX] = {
|
||||
static const unsigned int axismap_abs[INPUT_AXIS__MAX] = {
|
||||
[INPUT_AXIS_X] = ABS_X,
|
||||
[INPUT_AXIS_Y] = ABS_Y,
|
||||
};
|
||||
|
|
|
@ -520,66 +520,6 @@ void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
|
|||
void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason);
|
||||
bool bdrv_op_blocker_is_empty(BlockDriverState *bs);
|
||||
|
||||
typedef enum {
|
||||
BLKDBG_L1_UPDATE,
|
||||
|
||||
BLKDBG_L1_GROW_ALLOC_TABLE,
|
||||
BLKDBG_L1_GROW_WRITE_TABLE,
|
||||
BLKDBG_L1_GROW_ACTIVATE_TABLE,
|
||||
|
||||
BLKDBG_L2_LOAD,
|
||||
BLKDBG_L2_UPDATE,
|
||||
BLKDBG_L2_UPDATE_COMPRESSED,
|
||||
BLKDBG_L2_ALLOC_COW_READ,
|
||||
BLKDBG_L2_ALLOC_WRITE,
|
||||
|
||||
BLKDBG_READ_AIO,
|
||||
BLKDBG_READ_BACKING_AIO,
|
||||
BLKDBG_READ_COMPRESSED,
|
||||
|
||||
BLKDBG_WRITE_AIO,
|
||||
BLKDBG_WRITE_COMPRESSED,
|
||||
|
||||
BLKDBG_VMSTATE_LOAD,
|
||||
BLKDBG_VMSTATE_SAVE,
|
||||
|
||||
BLKDBG_COW_READ,
|
||||
BLKDBG_COW_WRITE,
|
||||
|
||||
BLKDBG_REFTABLE_LOAD,
|
||||
BLKDBG_REFTABLE_GROW,
|
||||
BLKDBG_REFTABLE_UPDATE,
|
||||
|
||||
BLKDBG_REFBLOCK_LOAD,
|
||||
BLKDBG_REFBLOCK_UPDATE,
|
||||
BLKDBG_REFBLOCK_UPDATE_PART,
|
||||
BLKDBG_REFBLOCK_ALLOC,
|
||||
BLKDBG_REFBLOCK_ALLOC_HOOKUP,
|
||||
BLKDBG_REFBLOCK_ALLOC_WRITE,
|
||||
BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS,
|
||||
BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE,
|
||||
BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE,
|
||||
|
||||
BLKDBG_CLUSTER_ALLOC,
|
||||
BLKDBG_CLUSTER_ALLOC_BYTES,
|
||||
BLKDBG_CLUSTER_FREE,
|
||||
|
||||
BLKDBG_FLUSH_TO_OS,
|
||||
BLKDBG_FLUSH_TO_DISK,
|
||||
|
||||
BLKDBG_PWRITEV_RMW_HEAD,
|
||||
BLKDBG_PWRITEV_RMW_AFTER_HEAD,
|
||||
BLKDBG_PWRITEV_RMW_TAIL,
|
||||
BLKDBG_PWRITEV_RMW_AFTER_TAIL,
|
||||
BLKDBG_PWRITEV,
|
||||
BLKDBG_PWRITEV_ZERO,
|
||||
BLKDBG_PWRITEV_DONE,
|
||||
|
||||
BLKDBG_EMPTY_IMAGE_PREPARE,
|
||||
|
||||
BLKDBG_EVENT_MAX,
|
||||
} BlkDebugEvent;
|
||||
|
||||
#define BLKDBG_EVENT(child, evt) \
|
||||
do { \
|
||||
if (child) { \
|
||||
|
@ -587,7 +527,7 @@ typedef enum {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event);
|
||||
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event);
|
||||
|
||||
int bdrv_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
const char *tag);
|
||||
|
|
|
@ -244,7 +244,7 @@ struct BlockDriver {
|
|||
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
|
||||
BlockDriverAmendStatusCB *status_cb);
|
||||
|
||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event);
|
||||
|
||||
/* TODO Better pass a option string/QDict/QemuOpts to add any rule? */
|
||||
int (*bdrv_debug_breakpoint)(BlockDriverState *bs, const char *event,
|
||||
|
|
|
@ -239,7 +239,7 @@ struct Property {
|
|||
PropertyInfo *info;
|
||||
ptrdiff_t offset;
|
||||
uint8_t bitnr;
|
||||
qtype_code qtype;
|
||||
QType qtype;
|
||||
int64_t defval;
|
||||
int arrayoffset;
|
||||
PropertyInfo *arrayinfo;
|
||||
|
|
|
@ -133,7 +133,7 @@ struct MigrationState
|
|||
QemuThread thread;
|
||||
QEMUBH *cleanup_bh;
|
||||
QEMUFile *file;
|
||||
int parameters[MIGRATION_PARAMETER_MAX];
|
||||
int parameters[MIGRATION_PARAMETER__MAX];
|
||||
|
||||
int state;
|
||||
MigrationParams params;
|
||||
|
@ -151,7 +151,7 @@ struct MigrationState
|
|||
int64_t expected_downtime;
|
||||
int64_t dirty_pages_rate;
|
||||
int64_t dirty_bytes_rate;
|
||||
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
|
||||
bool enabled_capabilities[MIGRATION_CAPABILITY__MAX];
|
||||
int64_t xbzrle_cache_size;
|
||||
int64_t setup_time;
|
||||
int64_t dirty_sync_count;
|
||||
|
|
|
@ -90,6 +90,20 @@
|
|||
*/
|
||||
typedef struct Error Error;
|
||||
|
||||
/*
|
||||
* Overall category of an error.
|
||||
* Based on the qapi type QapiErrorClass, but reproduced here for nicer
|
||||
* enum names.
|
||||
*/
|
||||
typedef enum ErrorClass {
|
||||
ERROR_CLASS_GENERIC_ERROR = QAPI_ERROR_CLASS_GENERICERROR,
|
||||
ERROR_CLASS_COMMAND_NOT_FOUND = QAPI_ERROR_CLASS_COMMANDNOTFOUND,
|
||||
ERROR_CLASS_DEVICE_ENCRYPTED = QAPI_ERROR_CLASS_DEVICEENCRYPTED,
|
||||
ERROR_CLASS_DEVICE_NOT_ACTIVE = QAPI_ERROR_CLASS_DEVICENOTACTIVE,
|
||||
ERROR_CLASS_DEVICE_NOT_FOUND = QAPI_ERROR_CLASS_DEVICENOTFOUND,
|
||||
ERROR_CLASS_KVM_MISSING_CAP = QAPI_ERROR_CLASS_KVMMISSINGCAP,
|
||||
} ErrorClass;
|
||||
|
||||
/*
|
||||
* Get @err's human-readable error message.
|
||||
*/
|
||||
|
|
|
@ -25,5 +25,6 @@ typedef struct QBool {
|
|||
QBool *qbool_from_bool(bool value);
|
||||
bool qbool_get_bool(const QBool *qb);
|
||||
QBool *qobject_to_qbool(const QObject *obj);
|
||||
void qbool_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QBOOL_H */
|
||||
|
|
|
@ -48,6 +48,7 @@ void qdict_iter(const QDict *qdict,
|
|||
void *opaque);
|
||||
const QDictEntry *qdict_first(const QDict *qdict);
|
||||
const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry);
|
||||
void qdict_destroy_obj(QObject *obj);
|
||||
|
||||
/* Helper to qdict_put_obj(), accepts any object */
|
||||
#define qdict_put(qdict, key, obj) \
|
||||
|
|
|
@ -25,5 +25,6 @@ typedef struct QFloat {
|
|||
QFloat *qfloat_from_double(double value);
|
||||
double qfloat_get_double(const QFloat *qi);
|
||||
QFloat *qobject_to_qfloat(const QObject *obj);
|
||||
void qfloat_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QFLOAT_H */
|
||||
|
|
|
@ -24,5 +24,6 @@ typedef struct QInt {
|
|||
QInt *qint_from_int(int64_t value);
|
||||
int64_t qint_get_int(const QInt *qi);
|
||||
QInt *qobject_to_qint(const QObject *obj);
|
||||
void qint_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QINT_H */
|
||||
|
|
|
@ -49,6 +49,7 @@ QObject *qlist_peek(QList *qlist);
|
|||
int qlist_empty(const QList *qlist);
|
||||
size_t qlist_size(const QList *qlist);
|
||||
QList *qobject_to_qlist(const QObject *obj);
|
||||
void qlist_destroy_obj(QObject *obj);
|
||||
|
||||
static inline const QListEntry *qlist_first(const QList *qlist)
|
||||
{
|
||||
|
|
|
@ -34,30 +34,12 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include "qapi-types.h"
|
||||
|
||||
typedef enum {
|
||||
QTYPE_NONE, /* sentinel value, no QObject has this type code */
|
||||
QTYPE_QNULL,
|
||||
QTYPE_QINT,
|
||||
QTYPE_QSTRING,
|
||||
QTYPE_QDICT,
|
||||
QTYPE_QLIST,
|
||||
QTYPE_QFLOAT,
|
||||
QTYPE_QBOOL,
|
||||
QTYPE_MAX,
|
||||
} qtype_code;
|
||||
|
||||
struct QObject;
|
||||
|
||||
typedef struct QType {
|
||||
qtype_code code;
|
||||
void (*destroy)(struct QObject *);
|
||||
} QType;
|
||||
|
||||
typedef struct QObject {
|
||||
const QType *type;
|
||||
struct QObject {
|
||||
QType type;
|
||||
size_t refcnt;
|
||||
} QObject;
|
||||
};
|
||||
|
||||
/* Get the 'base' part of an object */
|
||||
#define QOBJECT(obj) (&(obj)->base)
|
||||
|
@ -71,9 +53,12 @@ typedef struct QObject {
|
|||
qobject_decref(obj ? QOBJECT(obj) : NULL)
|
||||
|
||||
/* Initialize an object to default values */
|
||||
#define QOBJECT_INIT(obj, qtype_type) \
|
||||
obj->base.refcnt = 1; \
|
||||
obj->base.type = qtype_type
|
||||
static inline void qobject_init(QObject *obj, QType type)
|
||||
{
|
||||
assert(QTYPE_NONE < type && type < QTYPE__MAX);
|
||||
obj->refcnt = 1;
|
||||
obj->type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_incref(): Increment QObject's reference count
|
||||
|
@ -84,6 +69,11 @@ static inline void qobject_incref(QObject *obj)
|
|||
obj->refcnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_destroy(): Free resources used by the object
|
||||
*/
|
||||
void qobject_destroy(QObject *obj);
|
||||
|
||||
/**
|
||||
* qobject_decref(): Decrement QObject's reference count, deallocate
|
||||
* when it reaches zero
|
||||
|
@ -92,19 +82,17 @@ static inline void qobject_decref(QObject *obj)
|
|||
{
|
||||
assert(!obj || obj->refcnt);
|
||||
if (obj && --obj->refcnt == 0) {
|
||||
assert(obj->type != NULL);
|
||||
assert(obj->type->destroy != NULL);
|
||||
obj->type->destroy(obj);
|
||||
qobject_destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_type(): Return the QObject's type
|
||||
*/
|
||||
static inline qtype_code qobject_type(const QObject *obj)
|
||||
static inline QType qobject_type(const QObject *obj)
|
||||
{
|
||||
assert(obj->type != NULL);
|
||||
return obj->type->code;
|
||||
assert(QTYPE_NONE < obj->type && obj->type < QTYPE__MAX);
|
||||
return obj->type;
|
||||
}
|
||||
|
||||
extern QObject qnull_;
|
||||
|
|
|
@ -32,5 +32,6 @@ void qstring_append_int(QString *qstring, int64_t value);
|
|||
void qstring_append(QString *qstring, const char *str);
|
||||
void qstring_append_chr(QString *qstring, int c);
|
||||
QString *qobject_to_qstring(const QObject *obj);
|
||||
void qstring_destroy_obj(QObject *obj);
|
||||
|
||||
#endif /* QSTRING_H */
|
||||
|
|
|
@ -32,7 +32,8 @@ struct Visitor
|
|||
|
||||
void (*type_enum)(Visitor *v, int *obj, const char * const strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
|
||||
/* May be NULL; only needed for input visitors. */
|
||||
void (*get_next_type)(Visitor *v, QType *type, bool promote_int,
|
||||
const char *name, Error **errp);
|
||||
|
||||
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
|
||||
|
@ -43,9 +44,8 @@ struct Visitor
|
|||
void (*type_any)(Visitor *v, QObject **obj, const char *name,
|
||||
Error **errp);
|
||||
|
||||
/* May be NULL */
|
||||
void (*optional)(Visitor *v, bool *present, const char *name,
|
||||
Error **errp);
|
||||
/* May be NULL; most useful for input visitors. */
|
||||
void (*optional)(Visitor *v, bool *present, const char *name);
|
||||
|
||||
void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
|
||||
void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
|
||||
|
|
|
@ -27,9 +27,6 @@ typedef struct GenericList
|
|||
struct GenericList *next;
|
||||
} GenericList;
|
||||
|
||||
void visit_start_handle(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, Error **errp);
|
||||
void visit_end_handle(Visitor *v, Error **errp);
|
||||
void visit_start_struct(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, size_t size, Error **errp);
|
||||
void visit_end_struct(Visitor *v, Error **errp);
|
||||
|
@ -39,9 +36,22 @@ void visit_end_implicit_struct(Visitor *v, Error **errp);
|
|||
void visit_start_list(Visitor *v, const char *name, Error **errp);
|
||||
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
|
||||
void visit_end_list(Visitor *v, Error **errp);
|
||||
void visit_optional(Visitor *v, bool *present, const char *name,
|
||||
Error **errp);
|
||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
||||
|
||||
/**
|
||||
* Check if an optional member @name of an object needs visiting.
|
||||
* For input visitors, set *@present according to whether the
|
||||
* corresponding visit_type_*() needs calling; for other visitors,
|
||||
* leave *@present unchanged. Return *@present for convenience.
|
||||
*/
|
||||
bool visit_optional(Visitor *v, bool *present, const char *name);
|
||||
|
||||
/**
|
||||
* Determine the qtype of the item @name in the current object visit.
|
||||
* For input visitors, set *@type to the correct qtype of a qapi
|
||||
* alternate type; for other visitors, leave *@type unchanged.
|
||||
* If @promote_int, treat integers as QTYPE_FLOAT.
|
||||
*/
|
||||
void visit_get_next_type(Visitor *v, QType *type, bool promote_int,
|
||||
const char *name, Error **errp);
|
||||
void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
|
|
|
@ -80,6 +80,7 @@ typedef struct QEMUSGList QEMUSGList;
|
|||
typedef struct QEMUSizedBuffer QEMUSizedBuffer;
|
||||
typedef struct QEMUTimer QEMUTimer;
|
||||
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
|
||||
typedef struct QObject QObject;
|
||||
typedef struct RAMBlock RAMBlock;
|
||||
typedef struct Range Range;
|
||||
typedef struct SerialState SerialState;
|
||||
|
|
|
@ -202,7 +202,7 @@ static int global_state_post_load(void *opaque, int version_id)
|
|||
s->received = true;
|
||||
trace_migrate_global_state_post_load(runstate);
|
||||
|
||||
r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE_MAX,
|
||||
r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
|
||||
-1, &local_err);
|
||||
|
||||
if (r == -1) {
|
||||
|
@ -479,7 +479,7 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
|
|||
int i;
|
||||
|
||||
caps = NULL; /* silence compiler warning */
|
||||
for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
|
||||
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
||||
if (head == NULL) {
|
||||
head = g_malloc0(sizeof(*caps));
|
||||
caps = head;
|
||||
|
|
18
monitor.c
18
monitor.c
|
@ -403,7 +403,7 @@ static QDict *build_qmp_error_dict(Error *err)
|
|||
QObject *obj;
|
||||
|
||||
obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %s } }",
|
||||
ErrorClass_lookup[error_get_class(err)],
|
||||
QapiErrorClass_lookup[error_get_class(err)],
|
||||
error_get_pretty(err));
|
||||
|
||||
return qobject_to_qdict(obj);
|
||||
|
@ -441,7 +441,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data,
|
|||
}
|
||||
|
||||
|
||||
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT_MAX] = {
|
||||
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
|
||||
/* Limit guest-triggerable events to 1 per second */
|
||||
[QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS },
|
||||
|
@ -481,7 +481,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
|
|||
MonitorQAPIEventConf *evconf;
|
||||
MonitorQAPIEventState *evstate;
|
||||
|
||||
assert(event < QAPI_EVENT_MAX);
|
||||
assert(event < QAPI_EVENT__MAX);
|
||||
evconf = &monitor_qapi_event_conf[event];
|
||||
trace_monitor_protocol_event_queue(event, qdict, evconf->rate);
|
||||
|
||||
|
@ -946,7 +946,7 @@ EventInfoList *qmp_query_events(Error **errp)
|
|||
EventInfoList *info, *ev_list = NULL;
|
||||
QAPIEvent e;
|
||||
|
||||
for (e = 0 ; e < QAPI_EVENT_MAX ; e++) {
|
||||
for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
|
||||
const char *event_name = QAPIEvent_lookup[e];
|
||||
assert(event_name != NULL);
|
||||
info = g_malloc0(sizeof(*info));
|
||||
|
@ -1375,7 +1375,7 @@ static void hmp_mouse_move(Monitor *mon, const QDict *qdict)
|
|||
if (dz_str) {
|
||||
dz = strtol(dz_str, NULL, 0);
|
||||
if (dz != 0) {
|
||||
button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
||||
button = (dz > 0) ? INPUT_BUTTON_WHEELUP : INPUT_BUTTON_WHEELDOWN;
|
||||
qemu_input_queue_btn(NULL, button, true);
|
||||
qemu_input_event_sync();
|
||||
qemu_input_queue_btn(NULL, button, false);
|
||||
|
@ -1386,7 +1386,7 @@ static void hmp_mouse_move(Monitor *mon, const QDict *qdict)
|
|||
|
||||
static void hmp_mouse_button(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
static uint32_t bmap[INPUT_BUTTON_MAX] = {
|
||||
static uint32_t bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
|
@ -3217,7 +3217,7 @@ void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
|
|||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; i < Q_KEY_CODE_MAX; i++) {
|
||||
for (i = 0; i < Q_KEY_CODE__MAX; i++) {
|
||||
if (!strncmp(str, QKeyCode_lookup[i], len)) {
|
||||
readline_add_completion(rs, QKeyCode_lookup[i]);
|
||||
}
|
||||
|
@ -3316,7 +3316,7 @@ void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
|
|||
readline_set_completion_index(rs, len);
|
||||
if (nb_args == 2) {
|
||||
int i;
|
||||
for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
|
||||
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
|
||||
const char *name = MigrationCapability_lookup[i];
|
||||
if (!strncmp(str, name, len)) {
|
||||
readline_add_completion(rs, name);
|
||||
|
@ -3337,7 +3337,7 @@ void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
|
|||
readline_set_completion_index(rs, len);
|
||||
if (nb_args == 2) {
|
||||
int i;
|
||||
for (i = 0; i < MIGRATION_PARAMETER_MAX; i++) {
|
||||
for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
|
||||
const char *name = MigrationParameter_lookup[i];
|
||||
if (!strncmp(str, name, len)) {
|
||||
readline_add_completion(rs, name);
|
||||
|
|
|
@ -943,7 +943,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name,
|
|||
}
|
||||
|
||||
|
||||
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
|
||||
static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND__MAX])(
|
||||
const NetClientOptions *opts,
|
||||
const char *name,
|
||||
NetClientState *peer, Error **errp) = {
|
||||
|
@ -1296,7 +1296,7 @@ void qmp_set_link(const char *name, bool up, Error **errp)
|
|||
int queues, i;
|
||||
|
||||
queues = qemu_find_net_clients_except(name, ncs,
|
||||
NET_CLIENT_OPTIONS_KIND_MAX,
|
||||
NET_CLIENT_OPTIONS_KIND__MAX,
|
||||
MAX_QUEUE_NUM);
|
||||
|
||||
if (queues == 0) {
|
||||
|
|
120
qapi-schema.json
120
qapi-schema.json
|
@ -744,43 +744,125 @@
|
|||
{ 'command': 'query-mice', 'returns': ['MouseInfo'] }
|
||||
|
||||
##
|
||||
# @CpuInfo:
|
||||
# @CpuInfoArch:
|
||||
#
|
||||
# Information about a virtual CPU
|
||||
# An enumeration of cpu types that enable additional information during
|
||||
# @query-cpus.
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'enum': 'CpuInfoArch',
|
||||
'data': ['x86', 'sparc', 'ppc', 'mips', 'tricore', 'other' ] }
|
||||
|
||||
##
|
||||
# @CpuInfoBase:
|
||||
#
|
||||
# Common information about a virtual CPU
|
||||
#
|
||||
# @CPU: the index of the virtual CPU
|
||||
#
|
||||
# @current: this only exists for backwards compatible and should be ignored
|
||||
# @current: this only exists for backwards compatibility and should be ignored
|
||||
#
|
||||
# @halted: true if the virtual CPU is in the halt state. Halt usually refers
|
||||
# to a processor specific low power mode.
|
||||
#
|
||||
# @qom_path: path to the CPU object in the QOM tree (since 2.4)
|
||||
#
|
||||
# @pc: #optional If the target is i386 or x86_64, this is the 64-bit instruction
|
||||
# pointer.
|
||||
# If the target is Sparc, this is the PC component of the
|
||||
# instruction pointer.
|
||||
#
|
||||
# @nip: #optional If the target is PPC, the instruction pointer
|
||||
#
|
||||
# @npc: #optional If the target is Sparc, the NPC component of the instruction
|
||||
# pointer
|
||||
#
|
||||
# @PC: #optional If the target is MIPS, the instruction pointer
|
||||
#
|
||||
# @thread_id: ID of the underlying host thread
|
||||
#
|
||||
# @arch: architecture of the cpu, which determines which additional fields
|
||||
# will be listed (since 2.6)
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Notes: @halted is a transient state that changes frequently. By the time the
|
||||
# data is sent to the client, the guest may no longer be halted.
|
||||
##
|
||||
{ 'struct': 'CpuInfo',
|
||||
{ 'struct': 'CpuInfoBase',
|
||||
'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool',
|
||||
'qom_path': 'str',
|
||||
'*pc': 'int', '*nip': 'int', '*npc': 'int', '*PC': 'int',
|
||||
'thread_id': 'int'} }
|
||||
'qom_path': 'str', 'thread_id': 'int', 'arch': 'CpuInfoArch' } }
|
||||
|
||||
##
|
||||
# @CpuInfo:
|
||||
#
|
||||
# Information about a virtual CPU
|
||||
#
|
||||
# Since: 0.14.0
|
||||
##
|
||||
{ 'union': 'CpuInfo', 'base': 'CpuInfoBase', 'discriminator': 'arch',
|
||||
'data': { 'x86': 'CpuInfoX86',
|
||||
'sparc': 'CpuInfoSPARC',
|
||||
'ppc': 'CpuInfoPPC',
|
||||
'mips': 'CpuInfoMIPS',
|
||||
'tricore': 'CpuInfoTricore',
|
||||
'other': 'CpuInfoOther' } }
|
||||
|
||||
##
|
||||
# @CpuInfoX86:
|
||||
#
|
||||
# Additional information about a virtual i386 or x86_64 CPU
|
||||
#
|
||||
# @pc: the 64-bit instruction pointer
|
||||
#
|
||||
# Since 2.6
|
||||
##
|
||||
{ 'struct': 'CpuInfoX86', 'data': { 'pc': 'int' } }
|
||||
|
||||
##
|
||||
# @CpuInfoSPARC:
|
||||
#
|
||||
# Additional information about a virtual SPARC CPU
|
||||
#
|
||||
# @pc: the PC component of the instruction pointer
|
||||
#
|
||||
# @npc: the NPC component of the instruction pointer
|
||||
#
|
||||
# Since 2.6
|
||||
##
|
||||
{ 'struct': 'CpuInfoSPARC', 'data': { 'pc': 'int', 'npc': 'int' } }
|
||||
|
||||
##
|
||||
# @CpuInfoPPC:
|
||||
#
|
||||
# Additional information about a virtual PPC CPU
|
||||
#
|
||||
# @nip: the instruction pointer
|
||||
#
|
||||
# Since 2.6
|
||||
##
|
||||
{ 'struct': 'CpuInfoPPC', 'data': { 'nip': 'int' } }
|
||||
|
||||
##
|
||||
# @CpuInfoMIPS:
|
||||
#
|
||||
# Additional information about a virtual MIPS CPU
|
||||
#
|
||||
# @PC: the instruction pointer
|
||||
#
|
||||
# Since 2.6
|
||||
##
|
||||
{ 'struct': 'CpuInfoMIPS', 'data': { 'PC': 'int' } }
|
||||
|
||||
##
|
||||
# @CpuInfoTricore:
|
||||
#
|
||||
# Additional information about a virtual Tricore CPU
|
||||
#
|
||||
# @PC: the instruction pointer
|
||||
#
|
||||
# Since 2.6
|
||||
##
|
||||
{ 'struct': 'CpuInfoTricore', 'data': { 'PC': 'int' } }
|
||||
|
||||
##
|
||||
# @CpuInfoOther:
|
||||
#
|
||||
# No additional information is available about the virtual CPU
|
||||
#
|
||||
# Since 2.6
|
||||
#
|
||||
##
|
||||
{ 'struct': 'CpuInfoOther', 'data': { } }
|
||||
|
||||
##
|
||||
# @query-cpus:
|
||||
|
|
|
@ -1776,21 +1776,23 @@
|
|||
# @BlkdebugEvent
|
||||
#
|
||||
# Trigger events supported by blkdebug.
|
||||
#
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum': 'BlkdebugEvent',
|
||||
'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
|
||||
'l1_grow.activate_table', 'l2_load', 'l2_update',
|
||||
'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
|
||||
{ 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG',
|
||||
'data': [ 'l1_update', 'l1_grow_alloc_table', 'l1_grow_write_table',
|
||||
'l1_grow_activate_table', 'l2_load', 'l2_update',
|
||||
'l2_update_compressed', 'l2_alloc_cow_read', 'l2_alloc_write',
|
||||
'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
|
||||
'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
|
||||
'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
|
||||
'refblock_load', 'refblock_update', 'refblock_update_part',
|
||||
'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
|
||||
'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
|
||||
'refblock_alloc.switch_table', 'cluster_alloc',
|
||||
'refblock_alloc', 'refblock_alloc_hookup', 'refblock_alloc_write',
|
||||
'refblock_alloc_write_blocks', 'refblock_alloc_write_table',
|
||||
'refblock_alloc_switch_table', 'cluster_alloc',
|
||||
'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
|
||||
'flush_to_disk', 'pwritev_rmw.head', 'pwritev_rmw.after_head',
|
||||
'pwritev_rmw.tail', 'pwritev_rmw.after_tail', 'pwritev',
|
||||
'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head',
|
||||
'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev',
|
||||
'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] }
|
||||
|
||||
##
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# QAPI common definitions
|
||||
|
||||
##
|
||||
# @ErrorClass
|
||||
# @QapiErrorClass
|
||||
#
|
||||
# QEMU error classes
|
||||
#
|
||||
|
@ -24,7 +24,8 @@
|
|||
#
|
||||
# Since: 1.2
|
||||
##
|
||||
{ 'enum': 'ErrorClass',
|
||||
{ 'enum': 'QapiErrorClass',
|
||||
# Keep this in sync with ErrorClass in error.h
|
||||
'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
|
||||
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
|
||||
|
||||
|
|
|
@ -488,7 +488,7 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
|
|||
|
||||
|
||||
static void
|
||||
opts_optional(Visitor *v, bool *present, const char *name, Error **errp)
|
||||
opts_optional(Visitor *v, bool *present, const char *name)
|
||||
{
|
||||
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
|
||||
|
||||
|
|
|
@ -73,19 +73,19 @@ void visit_end_union(Visitor *v, bool data_present, Error **errp)
|
|||
}
|
||||
}
|
||||
|
||||
void visit_optional(Visitor *v, bool *present, const char *name,
|
||||
Error **errp)
|
||||
bool visit_optional(Visitor *v, bool *present, const char *name)
|
||||
{
|
||||
if (v->optional) {
|
||||
v->optional(v, present, name, errp);
|
||||
v->optional(v, present, name);
|
||||
}
|
||||
return *present;
|
||||
}
|
||||
|
||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
||||
void visit_get_next_type(Visitor *v, QType *type, bool promote_int,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
if (v->get_next_type) {
|
||||
v->get_next_type(v, obj, qtypes, name, errp);
|
||||
v->get_next_type(v, type, promote_int, name, errp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
|
|||
QObject *qmp_build_error_object(Error *err)
|
||||
{
|
||||
return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
|
||||
ErrorClass_lookup[error_get_class(err)],
|
||||
QapiErrorClass_lookup[error_get_class(err)],
|
||||
error_get_pretty(err));
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ static void qmp_input_end_list(Visitor *v, Error **errp)
|
|||
qmp_input_pop(qiv, errp);
|
||||
}
|
||||
|
||||
static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
|
||||
static void qmp_input_get_next_type(Visitor *v, QType *type, bool promote_int,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
|
@ -218,7 +218,10 @@ static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
|
|||
error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
|
||||
return;
|
||||
}
|
||||
*kind = qobjects[qobject_type(qobj)];
|
||||
*type = qobject_type(qobj);
|
||||
if (promote_int && *type == QTYPE_QINT) {
|
||||
*type = QTYPE_QFLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
|
||||
|
@ -300,8 +303,7 @@ static void qmp_input_type_any(Visitor *v, QObject **obj, const char *name,
|
|||
*obj = qobj;
|
||||
}
|
||||
|
||||
static void qmp_input_optional(Visitor *v, bool *present, const char *name,
|
||||
Error **errp)
|
||||
static void qmp_input_optional(Visitor *v, bool *present, const char *name)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||
|
|
|
@ -299,8 +299,7 @@ static void parse_type_number(Visitor *v, double *obj, const char *name,
|
|||
*obj = val;
|
||||
}
|
||||
|
||||
static void parse_optional(Visitor *v, bool *present, const char *name,
|
||||
Error **errp)
|
||||
static void parse_optional(Visitor *v, bool *present, const char *name)
|
||||
{
|
||||
StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
|
||||
|
||||
|
|
|
@ -487,7 +487,7 @@ int main(int argc, char **argv)
|
|||
detect_zeroes =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
optarg,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
|
|
|
@ -2765,6 +2765,8 @@ Return a json-array. Each CPU is represented by a json-object, which contains:
|
|||
- "current": true if this is the current CPU, false otherwise (json-bool)
|
||||
- "halted": true if the cpu is halted, false otherwise (json-bool)
|
||||
- "qom_path": path to the CPU object in the QOM tree (json-str)
|
||||
- "arch": architecture of the cpu, which determines what additional
|
||||
keys will be present (json-str)
|
||||
- Current program counter. The key's name depends on the architecture:
|
||||
"pc": i386/x86_64 (json-int)
|
||||
"nip": PPC (json-int)
|
||||
|
@ -2782,6 +2784,7 @@ Example:
|
|||
"current":true,
|
||||
"halted":false,
|
||||
"qom_path":"/machine/unattached/device[0]",
|
||||
"arch":"x86",
|
||||
"pc":3227107138,
|
||||
"thread_id":3134
|
||||
},
|
||||
|
@ -2790,6 +2793,7 @@ Example:
|
|||
"current":false,
|
||||
"halted":true,
|
||||
"qom_path":"/machine/unattached/device[2]",
|
||||
"arch":"x86",
|
||||
"pc":7108165,
|
||||
"thread_id":3135
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
|
||||
util-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
|
||||
util-obj-y += qjson.o qobject.o json-lexer.o json-streamer.o json-parser.o
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qbool_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qbool_type = {
|
||||
.code = QTYPE_QBOOL,
|
||||
.destroy = qbool_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qbool_from_bool(): Create a new QBool from a bool
|
||||
*
|
||||
|
@ -32,8 +25,8 @@ QBool *qbool_from_bool(bool value)
|
|||
QBool *qb;
|
||||
|
||||
qb = g_malloc(sizeof(*qb));
|
||||
qobject_init(QOBJECT(qb), QTYPE_QBOOL);
|
||||
qb->value = value;
|
||||
QOBJECT_INIT(qb, &qbool_type);
|
||||
|
||||
return qb;
|
||||
}
|
||||
|
@ -61,7 +54,7 @@ QBool *qobject_to_qbool(const QObject *obj)
|
|||
* qbool_destroy_obj(): Free all memory allocated by a
|
||||
* QBool object
|
||||
*/
|
||||
static void qbool_destroy_obj(QObject *obj)
|
||||
void qbool_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qbool(obj));
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qdict_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qdict_type = {
|
||||
.code = QTYPE_QDICT,
|
||||
.destroy = qdict_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qdict_new(): Create a new QDict
|
||||
*
|
||||
|
@ -36,7 +29,7 @@ QDict *qdict_new(void)
|
|||
QDict *qdict;
|
||||
|
||||
qdict = g_malloc0(sizeof(*qdict));
|
||||
QOBJECT_INIT(qdict, &qdict_type);
|
||||
qobject_init(QOBJECT(qdict), QTYPE_QDICT);
|
||||
|
||||
return qdict;
|
||||
}
|
||||
|
@ -184,8 +177,7 @@ size_t qdict_size(const QDict *qdict)
|
|||
/**
|
||||
* qdict_get_obj(): Get a QObject of a specific type
|
||||
*/
|
||||
static QObject *qdict_get_obj(const QDict *qdict, const char *key,
|
||||
qtype_code type)
|
||||
static QObject *qdict_get_obj(const QDict *qdict, const char *key, QType type)
|
||||
{
|
||||
QObject *obj;
|
||||
|
||||
|
@ -441,7 +433,7 @@ void qdict_del(QDict *qdict, const char *key)
|
|||
/**
|
||||
* qdict_destroy_obj(): Free all the memory allocated by a QDict
|
||||
*/
|
||||
static void qdict_destroy_obj(QObject *obj)
|
||||
void qdict_destroy_obj(QObject *obj)
|
||||
{
|
||||
int i;
|
||||
QDict *qdict;
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qfloat_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qfloat_type = {
|
||||
.code = QTYPE_QFLOAT,
|
||||
.destroy = qfloat_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qfloat_from_int(): Create a new QFloat from a float
|
||||
*
|
||||
|
@ -32,8 +25,8 @@ QFloat *qfloat_from_double(double value)
|
|||
QFloat *qf;
|
||||
|
||||
qf = g_malloc(sizeof(*qf));
|
||||
qobject_init(QOBJECT(qf), QTYPE_QFLOAT);
|
||||
qf->value = value;
|
||||
QOBJECT_INIT(qf, &qfloat_type);
|
||||
|
||||
return qf;
|
||||
}
|
||||
|
@ -61,7 +54,7 @@ QFloat *qobject_to_qfloat(const QObject *obj)
|
|||
* qfloat_destroy_obj(): Free all memory allocated by a
|
||||
* QFloat object
|
||||
*/
|
||||
static void qfloat_destroy_obj(QObject *obj)
|
||||
void qfloat_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qfloat(obj));
|
||||
|
|
|
@ -14,13 +14,6 @@
|
|||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qint_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qint_type = {
|
||||
.code = QTYPE_QINT,
|
||||
.destroy = qint_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qint_from_int(): Create a new QInt from an int64_t
|
||||
*
|
||||
|
@ -31,8 +24,8 @@ QInt *qint_from_int(int64_t value)
|
|||
QInt *qi;
|
||||
|
||||
qi = g_malloc(sizeof(*qi));
|
||||
qobject_init(QOBJECT(qi), QTYPE_QINT);
|
||||
qi->value = value;
|
||||
QOBJECT_INIT(qi, &qint_type);
|
||||
|
||||
return qi;
|
||||
}
|
||||
|
@ -60,7 +53,7 @@ QInt *qobject_to_qint(const QObject *obj)
|
|||
* qint_destroy_obj(): Free all memory allocated by a
|
||||
* QInt object
|
||||
*/
|
||||
static void qint_destroy_obj(QObject *obj)
|
||||
void qint_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
g_free(qobject_to_qint(obj));
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
#include "qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qlist_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qlist_type = {
|
||||
.code = QTYPE_QLIST,
|
||||
.destroy = qlist_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qlist_new(): Create a new QList
|
||||
*
|
||||
|
@ -32,8 +25,8 @@ QList *qlist_new(void)
|
|||
QList *qlist;
|
||||
|
||||
qlist = g_malloc(sizeof(*qlist));
|
||||
qobject_init(QOBJECT(qlist), QTYPE_QLIST);
|
||||
QTAILQ_INIT(&qlist->head);
|
||||
QOBJECT_INIT(qlist, &qlist_type);
|
||||
|
||||
return qlist;
|
||||
}
|
||||
|
@ -151,7 +144,7 @@ QList *qobject_to_qlist(const QObject *obj)
|
|||
/**
|
||||
* qlist_destroy_obj(): Free all the memory allocated by a QList
|
||||
*/
|
||||
static void qlist_destroy_obj(QObject *obj)
|
||||
void qlist_destroy_obj(QObject *obj)
|
||||
{
|
||||
QList *qlist;
|
||||
QListEntry *entry, *next_entry;
|
||||
|
|
|
@ -13,17 +13,7 @@
|
|||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
static void qnull_destroy_obj(QObject *obj)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static const QType qnull_type = {
|
||||
.code = QTYPE_QNULL,
|
||||
.destroy = qnull_destroy_obj,
|
||||
};
|
||||
|
||||
QObject qnull_ = {
|
||||
.type = &qnull_type,
|
||||
.type = QTYPE_QNULL,
|
||||
.refcnt = 1,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* QObject
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1
|
||||
* or later. See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
static void (*qdestroy[QTYPE__MAX])(QObject *) = {
|
||||
[QTYPE_NONE] = NULL, /* No such object exists */
|
||||
[QTYPE_QNULL] = NULL, /* qnull_ is indestructible */
|
||||
[QTYPE_QINT] = qint_destroy_obj,
|
||||
[QTYPE_QSTRING] = qstring_destroy_obj,
|
||||
[QTYPE_QDICT] = qdict_destroy_obj,
|
||||
[QTYPE_QLIST] = qlist_destroy_obj,
|
||||
[QTYPE_QFLOAT] = qfloat_destroy_obj,
|
||||
[QTYPE_QBOOL] = qbool_destroy_obj,
|
||||
};
|
||||
|
||||
void qobject_destroy(QObject *obj)
|
||||
{
|
||||
assert(!obj->refcnt);
|
||||
assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX);
|
||||
qdestroy[obj->type](obj);
|
||||
}
|
|
@ -14,13 +14,6 @@
|
|||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void qstring_destroy_obj(QObject *obj);
|
||||
|
||||
static const QType qstring_type = {
|
||||
.code = QTYPE_QSTRING,
|
||||
.destroy = qstring_destroy_obj,
|
||||
};
|
||||
|
||||
/**
|
||||
* qstring_new(): Create a new empty QString
|
||||
*
|
||||
|
@ -49,6 +42,7 @@ QString *qstring_from_substr(const char *str, int start, int end)
|
|||
QString *qstring;
|
||||
|
||||
qstring = g_malloc(sizeof(*qstring));
|
||||
qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
|
||||
|
||||
qstring->length = end - start + 1;
|
||||
qstring->capacity = qstring->length;
|
||||
|
@ -57,7 +51,6 @@ QString *qstring_from_substr(const char *str, int start, int end)
|
|||
memcpy(qstring->string, str + start, qstring->length);
|
||||
qstring->string[qstring->length] = 0;
|
||||
|
||||
QOBJECT_INIT(qstring, &qstring_type);
|
||||
|
||||
return qstring;
|
||||
}
|
||||
|
@ -138,7 +131,7 @@ const char *qstring_get_str(const QString *qstring)
|
|||
* qstring_destroy_obj(): Free all memory allocated by a QString
|
||||
* object
|
||||
*/
|
||||
static void qstring_destroy_obj(QObject *obj)
|
||||
void qstring_destroy_obj(QObject *obj)
|
||||
{
|
||||
QString *qs;
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ void replay_save_input_event(InputEvent *evt)
|
|||
replay_put_dword(evt->u.key->key->u.qcode);
|
||||
replay_put_byte(evt->u.key->down);
|
||||
break;
|
||||
case KEY_VALUE_KIND_MAX:
|
||||
case KEY_VALUE_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ void replay_save_input_event(InputEvent *evt)
|
|||
replay_put_dword(evt->u.abs->axis);
|
||||
replay_put_qword(evt->u.abs->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MAX:
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ InputEvent *replay_read_input_event(void)
|
|||
evt.u.key->key->u.qcode = (QKeyCode)replay_get_dword();
|
||||
evt.u.key->down = replay_get_byte();
|
||||
break;
|
||||
case KEY_VALUE_KIND_MAX:
|
||||
case KEY_VALUE_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ InputEvent *replay_read_input_event(void)
|
|||
evt.u.abs->axis = (InputAxis)replay_get_dword();
|
||||
evt.u.abs->value = replay_get_qword();
|
||||
break;
|
||||
case INPUT_EVENT_KIND_MAX:
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,54 +36,47 @@ struct %(c_name)s {
|
|||
c_name=c_name(name), c_type=element_type.c_type())
|
||||
|
||||
|
||||
def gen_struct_field(member):
|
||||
def gen_struct_fields(members):
|
||||
ret = ''
|
||||
|
||||
if member.optional:
|
||||
ret += mcgen('''
|
||||
for memb in members:
|
||||
if memb.optional:
|
||||
ret += mcgen('''
|
||||
bool has_%(c_name)s;
|
||||
''',
|
||||
c_name=c_name(member.name))
|
||||
ret += mcgen('''
|
||||
c_name=c_name(memb.name))
|
||||
ret += mcgen('''
|
||||
%(c_type)s %(c_name)s;
|
||||
''',
|
||||
c_type=member.type.c_type(), c_name=c_name(member.name))
|
||||
c_type=memb.type.c_type(), c_name=c_name(memb.name))
|
||||
return ret
|
||||
|
||||
|
||||
def gen_struct_fields(local_members, base=None):
|
||||
ret = ''
|
||||
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
/* Members inherited from %(c_name)s: */
|
||||
''',
|
||||
c_name=base.c_name())
|
||||
for memb in base.members:
|
||||
ret += gen_struct_field(memb)
|
||||
ret += mcgen('''
|
||||
/* Own members: */
|
||||
''')
|
||||
|
||||
for memb in local_members:
|
||||
ret += gen_struct_field(memb)
|
||||
return ret
|
||||
|
||||
|
||||
def gen_struct(name, base, members):
|
||||
def gen_object(name, base, members, variants):
|
||||
ret = mcgen('''
|
||||
|
||||
struct %(c_name)s {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
|
||||
ret += gen_struct_fields(members, base)
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
/* Members inherited from %(c_name)s: */
|
||||
''',
|
||||
c_name=base.c_name())
|
||||
ret += gen_struct_fields(base.members)
|
||||
ret += mcgen('''
|
||||
/* Own members: */
|
||||
''')
|
||||
ret += gen_struct_fields(members)
|
||||
|
||||
if variants:
|
||||
ret += gen_variants(variants)
|
||||
|
||||
# Make sure that all structs have at least one field; this avoids
|
||||
# potential issues with attempting to malloc space for zero-length
|
||||
# structs in C, and also incompatibility with C++ (where an empty
|
||||
# struct is size 1).
|
||||
if not (base and base.members) and not members:
|
||||
if not (base and base.members) and not members and not variants:
|
||||
ret += mcgen('''
|
||||
char qapi_dummy_field_for_empty_struct;
|
||||
''')
|
||||
|
@ -108,49 +101,7 @@ static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj)
|
|||
c_name=c_name(name), base=base.c_name())
|
||||
|
||||
|
||||
def gen_alternate_qtypes_decl(name):
|
||||
return mcgen('''
|
||||
|
||||
extern const int %(c_name)s_qtypes[];
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
|
||||
|
||||
def gen_alternate_qtypes(name, variants):
|
||||
ret = mcgen('''
|
||||
|
||||
const int %(c_name)s_qtypes[QTYPE_MAX] = {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
|
||||
for var in variants.variants:
|
||||
qtype = var.type.alternate_qtype()
|
||||
assert qtype
|
||||
|
||||
ret += mcgen('''
|
||||
[%(qtype)s] = %(enum_const)s,
|
||||
''',
|
||||
qtype=qtype,
|
||||
enum_const=c_enum_const(variants.tag_member.type.name,
|
||||
var.name))
|
||||
|
||||
ret += mcgen('''
|
||||
};
|
||||
''')
|
||||
return ret
|
||||
|
||||
|
||||
def gen_union(name, base, variants):
|
||||
ret = mcgen('''
|
||||
|
||||
struct %(c_name)s {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
if base:
|
||||
ret += gen_struct_fields([], base)
|
||||
else:
|
||||
ret += gen_struct_field(variants.tag_member)
|
||||
|
||||
def gen_variants(variants):
|
||||
# FIXME: What purpose does data serve, besides preventing a union that
|
||||
# has a branch named 'data'? We use it in qapi-visit.py to decide
|
||||
# whether to bypass the switch statement if visiting the discriminator
|
||||
|
@ -159,11 +110,11 @@ struct %(c_name)s {
|
|||
# should not be any data leaks even without a data pointer. Or, if
|
||||
# 'data' is merely added to guarantee we don't have an empty union,
|
||||
# shouldn't we enforce that at .json parse time?
|
||||
ret += mcgen('''
|
||||
ret = mcgen('''
|
||||
union { /* union tag is @%(c_name)s */
|
||||
void *data;
|
||||
''',
|
||||
c_name=c_name(variants.tag_member.name))
|
||||
c_name=c_name(variants.tag_member.name))
|
||||
|
||||
for var in variants.variants:
|
||||
# Ugly special case for simple union TODO get rid of it
|
||||
|
@ -176,7 +127,6 @@ struct %(c_name)s {
|
|||
|
||||
ret += mcgen('''
|
||||
} u;
|
||||
};
|
||||
''')
|
||||
|
||||
return ret
|
||||
|
@ -218,21 +168,17 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
|
|||
self.decl = None
|
||||
self.defn = None
|
||||
self._fwdecl = None
|
||||
self._fwdefn = None
|
||||
self._btin = None
|
||||
|
||||
def visit_begin(self, schema):
|
||||
self.decl = ''
|
||||
self.defn = ''
|
||||
self._fwdecl = ''
|
||||
self._fwdefn = ''
|
||||
self._btin = guardstart('QAPI_TYPES_BUILTIN')
|
||||
|
||||
def visit_end(self):
|
||||
self.decl = self._fwdecl + self.decl
|
||||
self._fwdecl = None
|
||||
self.defn = self._fwdefn + self.defn
|
||||
self._fwdefn = None
|
||||
# To avoid header dependency hell, we always generate
|
||||
# declarations for built-in types in our header files and
|
||||
# simply guard them. See also do_builtins (command line
|
||||
|
@ -251,8 +197,15 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
|
|||
self.defn += gen_type_cleanup(name)
|
||||
|
||||
def visit_enum_type(self, name, info, values, prefix):
|
||||
self._fwdecl += gen_enum(name, values, prefix)
|
||||
self._fwdefn += gen_enum_lookup(name, values, prefix)
|
||||
# Special case for our lone builtin enum type
|
||||
# TODO use something cleaner than existence of info
|
||||
if not info:
|
||||
self._btin += gen_enum(name, values, prefix)
|
||||
if do_builtins:
|
||||
self.defn += gen_enum_lookup(name, values, prefix)
|
||||
else:
|
||||
self._fwdecl += gen_enum(name, values, prefix)
|
||||
self.defn += gen_enum_lookup(name, values, prefix)
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
if isinstance(element_type, QAPISchemaBuiltinType):
|
||||
|
@ -268,20 +221,14 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
|
|||
|
||||
def visit_object_type(self, name, info, base, members, variants):
|
||||
self._fwdecl += gen_fwd_object_or_array(name)
|
||||
if variants:
|
||||
assert not members # not implemented
|
||||
self.decl += gen_union(name, base, variants)
|
||||
else:
|
||||
self.decl += gen_struct(name, base, members)
|
||||
self.decl += gen_object(name, base, members, variants)
|
||||
if base:
|
||||
self.decl += gen_upcast(name, base)
|
||||
self._gen_type_cleanup(name)
|
||||
|
||||
def visit_alternate_type(self, name, info, variants):
|
||||
self._fwdecl += gen_fwd_object_or_array(name)
|
||||
self._fwdefn += gen_alternate_qtypes(name, variants)
|
||||
self.decl += gen_union(name, None, variants)
|
||||
self.decl += gen_alternate_qtypes_decl(name)
|
||||
self.decl += gen_object(name, None, [variants.tag_member], variants)
|
||||
self._gen_type_cleanup(name)
|
||||
|
||||
# If you link code generated from multiple schemata, you want only one
|
||||
|
@ -338,10 +285,11 @@ fdef.write(mcgen('''
|
|||
''',
|
||||
prefix=prefix))
|
||||
|
||||
# To avoid circular headers, use only typedefs.h here, not qobject.h
|
||||
fdecl.write(mcgen('''
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu/typedefs.h"
|
||||
'''))
|
||||
|
||||
schema = QAPISchema(input_file)
|
||||
|
|
|
@ -172,6 +172,7 @@ out:
|
|||
|
||||
|
||||
def gen_visit_enum(name):
|
||||
# FIXME cast from enum *obj to int * invalidly assumes enum is int
|
||||
return mcgen('''
|
||||
|
||||
void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error **errp)
|
||||
|
@ -183,6 +184,11 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error
|
|||
|
||||
|
||||
def gen_visit_alternate(name, variants):
|
||||
promote_int = 'true'
|
||||
for var in variants.variants:
|
||||
if var.type.alternate_qtype() == 'QTYPE_QINT':
|
||||
promote_int = 'false'
|
||||
|
||||
ret = mcgen('''
|
||||
|
||||
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
||||
|
@ -193,13 +199,13 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
|
|||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
visit_get_next_type(v, (int*) &(*obj)->type, %(c_name)s_qtypes, name, &err);
|
||||
visit_get_next_type(v, &(*obj)->type, %(promote_int)s, name, &err);
|
||||
if (err) {
|
||||
goto out_obj;
|
||||
}
|
||||
switch ((*obj)->type) {
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
c_name=c_name(name), promote_int=promote_int)
|
||||
|
||||
for var in variants.variants:
|
||||
ret += mcgen('''
|
||||
|
@ -207,14 +213,14 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
|
|||
visit_type_%(c_type)s(v, &(*obj)->u.%(c_name)s, name, &err);
|
||||
break;
|
||||
''',
|
||||
case=c_enum_const(variants.tag_member.type.name,
|
||||
var.name),
|
||||
case=var.type.alternate_qtype(),
|
||||
c_type=var.type.c_name(),
|
||||
c_name=c_name(var.name))
|
||||
|
||||
ret += mcgen('''
|
||||
default:
|
||||
abort();
|
||||
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"%(name)s");
|
||||
}
|
||||
out_obj:
|
||||
error_propagate(errp, err);
|
||||
|
@ -223,7 +229,8 @@ out_obj:
|
|||
out:
|
||||
error_propagate(errp, err);
|
||||
}
|
||||
''')
|
||||
''',
|
||||
name=name)
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -347,8 +354,15 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
|||
isinstance(entity, QAPISchemaObjectType))
|
||||
|
||||
def visit_enum_type(self, name, info, values, prefix):
|
||||
self.decl += gen_visit_decl(name, scalar=True)
|
||||
self.defn += gen_visit_enum(name)
|
||||
# Special case for our lone builtin enum type
|
||||
# TODO use something cleaner than existence of info
|
||||
if not info:
|
||||
self._btin += gen_visit_decl(name, scalar=True)
|
||||
if do_builtins:
|
||||
self.defn += gen_visit_enum(name)
|
||||
else:
|
||||
self.decl += gen_visit_decl(name, scalar=True)
|
||||
self.defn += gen_visit_enum(name)
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
decl = gen_visit_decl(name)
|
||||
|
@ -364,7 +378,10 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
|||
def visit_object_type(self, name, info, base, members, variants):
|
||||
self.decl += gen_visit_decl(name)
|
||||
if variants:
|
||||
assert not members # not implemented
|
||||
if members:
|
||||
# Members other than variants.tag_member not implemented
|
||||
assert len(members) == 1
|
||||
assert members[0] == variants.tag_member
|
||||
self.defn += gen_visit_union(name, base, variants)
|
||||
else:
|
||||
self.defn += gen_visit_struct(name, base, members)
|
||||
|
@ -427,6 +444,7 @@ fdef.write(mcgen('''
|
|||
|
||||
fdecl.write(mcgen('''
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "%(prefix)sqapi-types.h"
|
||||
|
||||
''',
|
||||
|
|
295
scripts/qapi.py
295
scripts/qapi.py
|
@ -33,7 +33,8 @@ builtin_types = {
|
|||
'uint32': 'QTYPE_QINT',
|
||||
'uint64': 'QTYPE_QINT',
|
||||
'size': 'QTYPE_QINT',
|
||||
'any': None, # any qtype_code possible, actually
|
||||
'any': None, # any QType possible, actually
|
||||
'QType': 'QTYPE_QSTRING',
|
||||
}
|
||||
|
||||
# Whitelist of commands allowed to return a non-dictionary
|
||||
|
@ -58,6 +59,20 @@ returns_whitelist = [
|
|||
'guest-sync-delimited',
|
||||
]
|
||||
|
||||
# Whitelist of entities allowed to violate case conventions
|
||||
case_whitelist = [
|
||||
# From QMP:
|
||||
'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
|
||||
'CpuInfoBase', # CPU, visible through query-cpu
|
||||
'CpuInfoMIPS', # PC, visible through query-cpu
|
||||
'CpuInfoTricore', # PC, visible through query-cpu
|
||||
'InputAxis', # TODO: drop when x-input-send-event is fixed
|
||||
'InputButton', # TODO: drop when x-input-send-event is fixed
|
||||
'QapiErrorClass', # all members, visible through errors
|
||||
'UuidInfo', # UUID, visible through query-uuid
|
||||
'X86CPURegister32', # all members, visible indirectly through qom-get
|
||||
]
|
||||
|
||||
enum_types = []
|
||||
struct_types = []
|
||||
union_types = []
|
||||
|
@ -353,9 +368,11 @@ def discriminator_find_enum_define(expr):
|
|||
return find_enum(discriminator_type)
|
||||
|
||||
|
||||
# FIXME should enforce "other than downstream extensions [...], all
|
||||
# names should begin with a letter".
|
||||
valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$')
|
||||
# Names must be letters, numbers, -, and _. They must start with letter,
|
||||
# except for downstream extensions which must start with __RFQDN_.
|
||||
# Dots are only valid in the downstream extension prefix.
|
||||
valid_name = re.compile('^(__[a-zA-Z0-9.-]+_)?'
|
||||
'[a-zA-Z][a-zA-Z0-9_-]*$')
|
||||
|
||||
|
||||
def check_name(expr_info, source, name, allow_optional=False,
|
||||
|
@ -374,8 +391,8 @@ def check_name(expr_info, source, name, allow_optional=False,
|
|||
% (source, name))
|
||||
# Enum members can start with a digit, because the generated C
|
||||
# code always prefixes it with the enum name
|
||||
if enum_member:
|
||||
membername = '_' + membername
|
||||
if enum_member and membername[0].isdigit():
|
||||
membername = 'D' + membername
|
||||
# Reserve the entire 'q_' namespace for c_name()
|
||||
if not valid_name.match(membername) or \
|
||||
c_name(membername, False).startswith('q_'):
|
||||
|
@ -502,21 +519,6 @@ def check_type(expr_info, source, value, allow_array=False,
|
|||
'enum'])
|
||||
|
||||
|
||||
def check_member_clash(expr_info, base_name, data, source=""):
|
||||
base = find_struct(base_name)
|
||||
assert base
|
||||
base_members = base['data']
|
||||
for key in data.keys():
|
||||
if key.startswith('*'):
|
||||
key = key[1:]
|
||||
if key in base_members or "*" + key in base_members:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Member name '%s'%s clashes with base '%s'"
|
||||
% (key, source, base_name))
|
||||
if base.get('base'):
|
||||
check_member_clash(expr_info, base['base'], data, source)
|
||||
|
||||
|
||||
def check_command(expr, expr_info):
|
||||
name = expr['command']
|
||||
|
||||
|
@ -535,8 +537,6 @@ def check_event(expr, expr_info):
|
|||
global events
|
||||
name = expr['event']
|
||||
|
||||
if name.upper() == 'MAX':
|
||||
raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
|
||||
events.append(name)
|
||||
check_type(expr_info, "'data' for event '%s'" % name,
|
||||
expr.get('data'), allow_dict=True, allow_optional=True,
|
||||
|
@ -548,8 +548,6 @@ def check_union(expr, expr_info):
|
|||
base = expr.get('base')
|
||||
discriminator = expr.get('discriminator')
|
||||
members = expr['data']
|
||||
values = {'MAX': '(automatic)', 'KIND': '(automatic)',
|
||||
'TYPE': '(automatic)'}
|
||||
|
||||
# Two types of unions, determined by discriminator.
|
||||
|
||||
|
@ -596,59 +594,29 @@ def check_union(expr, expr_info):
|
|||
for (key, value) in members.items():
|
||||
check_name(expr_info, "Member of union '%s'" % name, key)
|
||||
|
||||
# Each value must name a known type; furthermore, in flat unions,
|
||||
# branches must be a struct with no overlapping member names
|
||||
# Each value must name a known type
|
||||
check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
|
||||
value, allow_array=not base, allow_metas=allow_metas)
|
||||
if base:
|
||||
branch_struct = find_struct(value)
|
||||
assert branch_struct
|
||||
check_member_clash(expr_info, base, branch_struct['data'],
|
||||
" of branch '%s'" % key)
|
||||
|
||||
# If the discriminator names an enum type, then all members
|
||||
# of 'data' must also be members of the enum type, which in turn
|
||||
# must not collide with the discriminator name.
|
||||
# of 'data' must also be members of the enum type.
|
||||
if enum_define:
|
||||
if key not in enum_define['enum_values']:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Discriminator value '%s' is not found in "
|
||||
"enum '%s'" %
|
||||
(key, enum_define["enum_name"]))
|
||||
if discriminator in enum_define['enum_values']:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Discriminator name '%s' collides with "
|
||||
"enum value in '%s'" %
|
||||
(discriminator, enum_define["enum_name"]))
|
||||
|
||||
# Otherwise, check for conflicts in the generated enum
|
||||
else:
|
||||
c_key = camel_to_upper(key)
|
||||
if c_key in values:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Union '%s' member '%s' clashes with '%s'"
|
||||
% (name, key, values[c_key]))
|
||||
values[c_key] = key
|
||||
|
||||
|
||||
def check_alternate(expr, expr_info):
|
||||
name = expr['alternate']
|
||||
members = expr['data']
|
||||
values = {'MAX': '(automatic)'}
|
||||
types_seen = {}
|
||||
|
||||
# Check every branch
|
||||
for (key, value) in members.items():
|
||||
check_name(expr_info, "Member of alternate '%s'" % name, key)
|
||||
|
||||
# Check for conflicts in the generated enum
|
||||
c_key = camel_to_upper(key)
|
||||
if c_key in values:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Alternate '%s' member '%s' clashes with '%s'"
|
||||
% (name, key, values[c_key]))
|
||||
values[c_key] = key
|
||||
|
||||
# Ensure alternates have no type conflicts.
|
||||
check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
|
||||
value,
|
||||
|
@ -667,7 +635,6 @@ def check_enum(expr, expr_info):
|
|||
name = expr['enum']
|
||||
members = expr.get('data')
|
||||
prefix = expr.get('prefix')
|
||||
values = {'MAX': '(automatic)'}
|
||||
|
||||
if not isinstance(members, list):
|
||||
raise QAPIExprError(expr_info,
|
||||
|
@ -678,12 +645,6 @@ def check_enum(expr, expr_info):
|
|||
for member in members:
|
||||
check_name(expr_info, "Member of enum '%s'" % name, member,
|
||||
enum_member=True)
|
||||
key = camel_to_upper(member)
|
||||
if key in values:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Enum '%s' member '%s' clashes with '%s'"
|
||||
% (name, member, values[key]))
|
||||
values[key] = member
|
||||
|
||||
|
||||
def check_struct(expr, expr_info):
|
||||
|
@ -694,8 +655,6 @@ def check_struct(expr, expr_info):
|
|||
allow_dict=True, allow_optional=True)
|
||||
check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
|
||||
allow_metas=['struct'])
|
||||
if expr.get('base'):
|
||||
check_member_clash(expr_info, expr['base'], expr['data'])
|
||||
|
||||
|
||||
def check_keys(expr_elem, meta, required, optional=[]):
|
||||
|
@ -907,13 +866,16 @@ class QAPISchemaEnumType(QAPISchemaType):
|
|||
def __init__(self, name, info, values, prefix):
|
||||
QAPISchemaType.__init__(self, name, info)
|
||||
for v in values:
|
||||
assert isinstance(v, str)
|
||||
assert isinstance(v, QAPISchemaMember)
|
||||
v.set_owner(name)
|
||||
assert prefix is None or isinstance(prefix, str)
|
||||
self.values = values
|
||||
self.prefix = prefix
|
||||
|
||||
def check(self, schema):
|
||||
assert len(set(self.values)) == len(self.values)
|
||||
seen = {}
|
||||
for v in self.values:
|
||||
v.check_clash(self.info, seen)
|
||||
|
||||
def is_implicit(self):
|
||||
# See QAPISchema._make_implicit_enum_type()
|
||||
|
@ -922,8 +884,11 @@ class QAPISchemaEnumType(QAPISchemaType):
|
|||
def c_type(self, is_param=False):
|
||||
return c_name(self.name)
|
||||
|
||||
def member_names(self):
|
||||
return [v.name for v in self.values]
|
||||
|
||||
def c_null(self):
|
||||
return c_enum_const(self.name, (self.values + ['MAX'])[0],
|
||||
return c_enum_const(self.name, (self.member_names() + ['_MAX'])[0],
|
||||
self.prefix)
|
||||
|
||||
def json_type(self):
|
||||
|
@ -931,7 +896,7 @@ class QAPISchemaEnumType(QAPISchemaType):
|
|||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_enum_type(self.name, self.info,
|
||||
self.values, self.prefix)
|
||||
self.member_names(), self.prefix)
|
||||
|
||||
|
||||
class QAPISchemaArrayType(QAPISchemaType):
|
||||
|
@ -957,12 +922,17 @@ class QAPISchemaArrayType(QAPISchemaType):
|
|||
|
||||
class QAPISchemaObjectType(QAPISchemaType):
|
||||
def __init__(self, name, info, base, local_members, variants):
|
||||
# struct has local_members, optional base, and no variants
|
||||
# flat union has base, variants, and no local_members
|
||||
# simple union has local_members, variants, and no base
|
||||
QAPISchemaType.__init__(self, name, info)
|
||||
assert base is None or isinstance(base, str)
|
||||
for m in local_members:
|
||||
assert isinstance(m, QAPISchemaObjectTypeMember)
|
||||
assert (variants is None or
|
||||
isinstance(variants, QAPISchemaObjectTypeVariants))
|
||||
m.set_owner(name)
|
||||
if variants is not None:
|
||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||
variants.set_owner(name)
|
||||
self._base_name = base
|
||||
self.base = None
|
||||
self.local_members = local_members
|
||||
|
@ -970,27 +940,34 @@ class QAPISchemaObjectType(QAPISchemaType):
|
|||
self.members = None
|
||||
|
||||
def check(self, schema):
|
||||
assert self.members is not False # not running in cycles
|
||||
if self.members is False: # check for cycles
|
||||
raise QAPIExprError(self.info,
|
||||
"Object %s contains itself" % self.name)
|
||||
if self.members:
|
||||
return
|
||||
self.members = False # mark as being checked
|
||||
seen = OrderedDict()
|
||||
if self._base_name:
|
||||
self.base = schema.lookup_type(self._base_name)
|
||||
assert isinstance(self.base, QAPISchemaObjectType)
|
||||
assert not self.base.variants # not implemented
|
||||
self.base.check(schema)
|
||||
members = list(self.base.members)
|
||||
else:
|
||||
members = []
|
||||
seen = {}
|
||||
for m in members:
|
||||
assert c_name(m.name) not in seen
|
||||
seen[m.name] = m
|
||||
self.base.check_clash(schema, self.info, seen)
|
||||
for m in self.local_members:
|
||||
m.check(schema, members, seen)
|
||||
m.check(schema)
|
||||
m.check_clash(self.info, seen)
|
||||
self.members = seen.values()
|
||||
if self.variants:
|
||||
self.variants.check(schema, members, seen)
|
||||
self.members = members
|
||||
self.variants.check(schema, seen)
|
||||
assert self.variants.tag_member in self.members
|
||||
self.variants.check_clash(schema, self.info, seen)
|
||||
|
||||
# Check that the members of this type do not cause duplicate JSON fields,
|
||||
# and update seen to track the members seen so far. Report any errors
|
||||
# on behalf of info, which is not necessarily self.info
|
||||
def check_clash(self, schema, info, seen):
|
||||
assert not self.variants # not implemented
|
||||
for m in self.members:
|
||||
m.check_clash(info, seen)
|
||||
|
||||
def is_implicit(self):
|
||||
# See QAPISchema._make_implicit_object_type()
|
||||
|
@ -1014,22 +991,63 @@ class QAPISchemaObjectType(QAPISchemaType):
|
|||
self.members, self.variants)
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeMember(object):
|
||||
def __init__(self, name, typ, optional):
|
||||
class QAPISchemaMember(object):
|
||||
role = 'member'
|
||||
|
||||
def __init__(self, name):
|
||||
assert isinstance(name, str)
|
||||
self.name = name
|
||||
self.owner = None
|
||||
|
||||
def set_owner(self, name):
|
||||
assert not self.owner
|
||||
self.owner = name
|
||||
|
||||
def check_clash(self, info, seen):
|
||||
cname = c_name(self.name)
|
||||
if cname.lower() != cname and self.owner not in case_whitelist:
|
||||
raise QAPIExprError(info,
|
||||
"%s should not use uppercase" % self.describe())
|
||||
if cname in seen:
|
||||
raise QAPIExprError(info,
|
||||
"%s collides with %s"
|
||||
% (self.describe(), seen[cname].describe()))
|
||||
seen[cname] = self
|
||||
|
||||
def _pretty_owner(self):
|
||||
owner = self.owner
|
||||
if owner.startswith(':obj-'):
|
||||
# See QAPISchema._make_implicit_object_type() - reverse the
|
||||
# mapping there to create a nice human-readable description
|
||||
owner = owner[5:]
|
||||
if owner.endswith('-arg'):
|
||||
return '(parameter of %s)' % owner[:-4]
|
||||
else:
|
||||
assert owner.endswith('-wrapper')
|
||||
# Unreachable and not implemented
|
||||
assert False
|
||||
if owner.endswith('Kind'):
|
||||
# See QAPISchema._make_implicit_enum_type()
|
||||
return '(branch of %s)' % owner[:-4]
|
||||
return '(%s of %s)' % (self.role, owner)
|
||||
|
||||
def describe(self):
|
||||
return "'%s' %s" % (self.name, self._pretty_owner())
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeMember(QAPISchemaMember):
|
||||
def __init__(self, name, typ, optional):
|
||||
QAPISchemaMember.__init__(self, name)
|
||||
assert isinstance(typ, str)
|
||||
assert isinstance(optional, bool)
|
||||
self.name = name
|
||||
self._type_name = typ
|
||||
self.type = None
|
||||
self.optional = optional
|
||||
|
||||
def check(self, schema, all_members, seen):
|
||||
assert self.name not in seen
|
||||
def check(self, schema):
|
||||
assert self.owner
|
||||
self.type = schema.lookup_type(self._type_name)
|
||||
assert self.type
|
||||
all_members.append(self)
|
||||
seen[self.name] = self
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeVariants(object):
|
||||
|
@ -1047,25 +1065,38 @@ class QAPISchemaObjectTypeVariants(object):
|
|||
self.tag_member = tag_member
|
||||
self.variants = variants
|
||||
|
||||
def check(self, schema, members, seen):
|
||||
if self.tag_name:
|
||||
self.tag_member = seen[self.tag_name]
|
||||
else:
|
||||
self.tag_member.check(schema, members, seen)
|
||||
def set_owner(self, name):
|
||||
for v in self.variants:
|
||||
v.set_owner(name)
|
||||
|
||||
def check(self, schema, seen):
|
||||
if not self.tag_member: # flat union
|
||||
self.tag_member = seen[c_name(self.tag_name)]
|
||||
assert self.tag_name == self.tag_member.name
|
||||
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
|
||||
for v in self.variants:
|
||||
vseen = dict(seen)
|
||||
v.check(schema, self.tag_member.type, vseen)
|
||||
v.check(schema)
|
||||
# Union names must match enum values; alternate names are
|
||||
# checked separately. Use 'seen' to tell the two apart.
|
||||
if seen:
|
||||
assert v.name in self.tag_member.type.member_names()
|
||||
assert isinstance(v.type, QAPISchemaObjectType)
|
||||
v.type.check(schema)
|
||||
|
||||
def check_clash(self, schema, info, seen):
|
||||
for v in self.variants:
|
||||
# Reset seen map for each variant, since qapi names from one
|
||||
# branch do not affect another branch
|
||||
assert isinstance(v.type, QAPISchemaObjectType)
|
||||
v.type.check_clash(schema, info, dict(seen))
|
||||
|
||||
|
||||
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
||||
role = 'branch'
|
||||
|
||||
def __init__(self, name, typ):
|
||||
QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
|
||||
|
||||
def check(self, schema, tag_type, seen):
|
||||
QAPISchemaObjectTypeMember.check(self, schema, [], seen)
|
||||
assert self.name in tag_type.values
|
||||
|
||||
# This function exists to support ugly simple union special cases
|
||||
# TODO get rid of them, and drop the function
|
||||
def simple_union_type(self):
|
||||
|
@ -1082,10 +1113,20 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
|||
QAPISchemaType.__init__(self, name, info)
|
||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||
assert not variants.tag_name
|
||||
variants.set_owner(name)
|
||||
variants.tag_member.set_owner(self.name)
|
||||
self.variants = variants
|
||||
|
||||
def check(self, schema):
|
||||
self.variants.check(schema, [], {})
|
||||
self.variants.tag_member.check(schema)
|
||||
# Not calling self.variants.check_clash(), because there's nothing
|
||||
# to clash with
|
||||
self.variants.check(schema, {})
|
||||
# Alternate branch names have no relation to the tag enum values;
|
||||
# so we have to check for potential name collisions ourselves.
|
||||
seen = {}
|
||||
for v in self.variants.variants:
|
||||
v.check_clash(self.info, seen)
|
||||
|
||||
def json_type(self):
|
||||
return 'value'
|
||||
|
@ -1196,10 +1237,20 @@ class QAPISchema(object):
|
|||
self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
|
||||
[], None)
|
||||
self._def_entity(self.the_empty_object_type)
|
||||
qtype_values = self._make_enum_members(['none', 'qnull', 'qint',
|
||||
'qstring', 'qdict', 'qlist',
|
||||
'qfloat', 'qbool'])
|
||||
self._def_entity(QAPISchemaEnumType('QType', None, qtype_values,
|
||||
'QTYPE'))
|
||||
|
||||
def _make_enum_members(self, values):
|
||||
return [QAPISchemaMember(v) for v in values]
|
||||
|
||||
def _make_implicit_enum_type(self, name, info, values):
|
||||
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
||||
name = name + 'Kind' # Use namespace reserved by add_name()
|
||||
self._def_entity(QAPISchemaEnumType(name, info, values, None))
|
||||
self._def_entity(QAPISchemaEnumType(
|
||||
name, info, self._make_enum_members(values), None))
|
||||
return name
|
||||
|
||||
def _make_array_type(self, element_type, info):
|
||||
|
@ -1211,6 +1262,7 @@ class QAPISchema(object):
|
|||
def _make_implicit_object_type(self, name, info, role, members):
|
||||
if not members:
|
||||
return None
|
||||
# See also QAPISchemaObjectTypeMember._pretty_owner()
|
||||
name = ':obj-%s-%s' % (name, role)
|
||||
if not self.lookup_entity(name, QAPISchemaObjectType):
|
||||
self._def_entity(QAPISchemaObjectType(name, info, None,
|
||||
|
@ -1221,7 +1273,8 @@ class QAPISchema(object):
|
|||
name = expr['enum']
|
||||
data = expr['data']
|
||||
prefix = expr.get('prefix')
|
||||
self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
|
||||
self._def_entity(QAPISchemaEnumType(
|
||||
name, info, self._make_enum_members(data), prefix))
|
||||
|
||||
def _make_member(self, name, typ, info):
|
||||
optional = False
|
||||
|
@ -1256,11 +1309,6 @@ class QAPISchema(object):
|
|||
typ, info, 'wrapper', [self._make_member('data', typ, info)])
|
||||
return QAPISchemaObjectTypeVariant(case, typ)
|
||||
|
||||
def _make_implicit_tag(self, type_name, info, variants):
|
||||
typ = self._make_implicit_enum_type(type_name, info,
|
||||
[v.name for v in variants])
|
||||
return QAPISchemaObjectTypeMember('type', typ, False)
|
||||
|
||||
def _def_union_type(self, expr, info):
|
||||
name = expr['union']
|
||||
data = expr['data']
|
||||
|
@ -1270,13 +1318,16 @@ class QAPISchema(object):
|
|||
if tag_name:
|
||||
variants = [self._make_variant(key, value)
|
||||
for (key, value) in data.iteritems()]
|
||||
members = []
|
||||
else:
|
||||
variants = [self._make_simple_variant(key, value, info)
|
||||
for (key, value) in data.iteritems()]
|
||||
tag_member = self._make_implicit_tag(name, info, variants)
|
||||
typ = self._make_implicit_enum_type(name, info,
|
||||
[v.name for v in variants])
|
||||
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
|
||||
members = [tag_member]
|
||||
self._def_entity(
|
||||
QAPISchemaObjectType(name, info, base,
|
||||
self._make_members(OrderedDict(), info),
|
||||
QAPISchemaObjectType(name, info, base, members,
|
||||
QAPISchemaObjectTypeVariants(tag_name,
|
||||
tag_member,
|
||||
variants)))
|
||||
|
@ -1286,7 +1337,7 @@ class QAPISchema(object):
|
|||
data = expr['data']
|
||||
variants = [self._make_variant(key, value)
|
||||
for (key, value) in data.iteritems()]
|
||||
tag_member = self._make_implicit_tag(name, info, variants)
|
||||
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
|
||||
self._def_entity(
|
||||
QAPISchemaAlternateType(name, info,
|
||||
QAPISchemaObjectTypeVariants(None,
|
||||
|
@ -1390,7 +1441,7 @@ def camel_to_upper(value):
|
|||
def c_enum_const(type_name, const_name, prefix=None):
|
||||
if prefix is not None:
|
||||
type_name = prefix
|
||||
return camel_to_upper(type_name + '_' + const_name)
|
||||
return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
|
||||
|
||||
c_name_trans = string.maketrans('.-', '__')
|
||||
|
||||
|
@ -1432,10 +1483,11 @@ def c_name(name, protect=True):
|
|||
'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
|
||||
# namespace pollution:
|
||||
polluted_words = set(['unix', 'errno'])
|
||||
name = name.translate(c_name_trans)
|
||||
if protect and (name in c89_words | c99_words | c11_words | gcc_words
|
||||
| cpp_words | polluted_words):
|
||||
return "q_" + name
|
||||
return name.translate(c_name_trans)
|
||||
return name
|
||||
|
||||
eatspace = '\033EATSPACE.'
|
||||
pointer_suffix = ' *' + eatspace
|
||||
|
@ -1515,7 +1567,7 @@ const char *const %(c_name)s_lookup[] = {
|
|||
''',
|
||||
index=index, value=value)
|
||||
|
||||
max_index = c_enum_const(name, 'MAX', prefix)
|
||||
max_index = c_enum_const(name, '_MAX', prefix)
|
||||
ret += mcgen('''
|
||||
[%(max_index)s] = NULL,
|
||||
};
|
||||
|
@ -1526,7 +1578,7 @@ const char *const %(c_name)s_lookup[] = {
|
|||
|
||||
def gen_enum(name, values, prefix=None):
|
||||
# append automatically generated _MAX value
|
||||
enum_values = values + ['MAX']
|
||||
enum_values = values + ['_MAX']
|
||||
|
||||
ret = mcgen('''
|
||||
|
||||
|
@ -1594,15 +1646,10 @@ def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False):
|
|||
for memb in members:
|
||||
if memb.optional:
|
||||
ret += mcgen('''
|
||||
visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s", %(errp)s);
|
||||
if (visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s")) {
|
||||
''',
|
||||
prefix=prefix, c_name=c_name(memb.name),
|
||||
name=memb.name, errp=errparg)
|
||||
ret += gen_err_check(skiperr=skiperr)
|
||||
ret += mcgen('''
|
||||
if (%(prefix)shas_%(c_name)s) {
|
||||
''',
|
||||
prefix=prefix, c_name=c_name(memb.name))
|
||||
push_indent()
|
||||
|
||||
# Ugly: sometimes we need to cast away const
|
||||
|
|
|
@ -246,6 +246,7 @@ qapi-schema += args-array-unknown.json
|
|||
qapi-schema += args-int.json
|
||||
qapi-schema += args-invalid.json
|
||||
qapi-schema += args-member-array-bad.json
|
||||
qapi-schema += args-member-case.json
|
||||
qapi-schema += args-member-unknown.json
|
||||
qapi-schema += args-name-clash.json
|
||||
qapi-schema += args-union.json
|
||||
|
@ -256,6 +257,8 @@ qapi-schema += bad-ident.json
|
|||
qapi-schema += bad-type-bool.json
|
||||
qapi-schema += bad-type-dict.json
|
||||
qapi-schema += bad-type-int.json
|
||||
qapi-schema += base-cycle-direct.json
|
||||
qapi-schema += base-cycle-indirect.json
|
||||
qapi-schema += command-int.json
|
||||
qapi-schema += comments.json
|
||||
qapi-schema += double-data.json
|
||||
|
@ -267,23 +270,20 @@ qapi-schema += enum-bad-prefix.json
|
|||
qapi-schema += enum-clash-member.json
|
||||
qapi-schema += enum-dict-member.json
|
||||
qapi-schema += enum-int-member.json
|
||||
qapi-schema += enum-max-member.json
|
||||
qapi-schema += enum-member-case.json
|
||||
qapi-schema += enum-missing-data.json
|
||||
qapi-schema += enum-wrong-data.json
|
||||
qapi-schema += escape-outside-string.json
|
||||
qapi-schema += escape-too-big.json
|
||||
qapi-schema += escape-too-short.json
|
||||
qapi-schema += event-case.json
|
||||
qapi-schema += event-max.json
|
||||
qapi-schema += event-nest-struct.json
|
||||
qapi-schema += flat-union-array-branch.json
|
||||
qapi-schema += flat-union-bad-base.json
|
||||
qapi-schema += flat-union-bad-discriminator.json
|
||||
qapi-schema += flat-union-base-any.json
|
||||
qapi-schema += flat-union-base-union.json
|
||||
qapi-schema += flat-union-clash-branch.json
|
||||
qapi-schema += flat-union-clash-member.json
|
||||
qapi-schema += flat-union-clash-type.json
|
||||
qapi-schema += flat-union-empty.json
|
||||
qapi-schema += flat-union-inline.json
|
||||
qapi-schema += flat-union-int-branch.json
|
||||
|
@ -320,9 +320,11 @@ qapi-schema += redefined-command.json
|
|||
qapi-schema += redefined-event.json
|
||||
qapi-schema += redefined-type.json
|
||||
qapi-schema += reserved-command-q.json
|
||||
qapi-schema += reserved-enum-q.json
|
||||
qapi-schema += reserved-member-has.json
|
||||
qapi-schema += reserved-member-q.json
|
||||
qapi-schema += reserved-member-u.json
|
||||
qapi-schema += reserved-member-underscore.json
|
||||
qapi-schema += reserved-type-kind.json
|
||||
qapi-schema += reserved-type-list.json
|
||||
qapi-schema += returns-alternate.json
|
||||
|
@ -341,14 +343,12 @@ qapi-schema += unclosed-list.json
|
|||
qapi-schema += unclosed-object.json
|
||||
qapi-schema += unclosed-string.json
|
||||
qapi-schema += unicode-str.json
|
||||
qapi-schema += union-bad-branch.json
|
||||
qapi-schema += union-base-no-discriminator.json
|
||||
qapi-schema += union-branch-case.json
|
||||
qapi-schema += union-clash-branches.json
|
||||
qapi-schema += union-clash-data.json
|
||||
qapi-schema += union-clash-type.json
|
||||
qapi-schema += union-empty.json
|
||||
qapi-schema += union-invalid-base.json
|
||||
qapi-schema += union-max.json
|
||||
qapi-schema += union-optional-branch.json
|
||||
qapi-schema += union-unknown.json
|
||||
qapi-schema += unknown-escape.json
|
||||
|
|
|
@ -1 +1 @@
|
|||
tests/qapi-schema/alternate-clash.json:7: Alternate 'Alt1' member 'a_b' clashes with 'a-b'
|
||||
tests/qapi-schema/alternate-clash.json:7: 'a_b' (branch of Alt1) collides with 'a-b' (branch of Alt1)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
object :empty
|
||||
alternate Alt
|
||||
case i: int
|
||||
enum AltKind ['i']
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-member-case.json:2: 'Arg' (parameter of no-way-this-will-get-whitelisted) should not use uppercase
|
|
@ -0,0 +1,2 @@
|
|||
# Member names should be 'lower-case' unless the struct/command is whitelisted
|
||||
{ 'command': 'no-way-this-will-get-whitelisted', 'data': { 'Arg': 'int' } }
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-name-clash.json:4: 'a_b' (parameter of oops) collides with 'a-b' (parameter of oops)
|
|
@ -1 +1 @@
|
|||
0
|
||||
1
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# C member name collision
|
||||
# FIXME - This parses, but fails to compile, because the C struct is given
|
||||
# two 'a_b' members. Either reject this at parse time, or munge the C names
|
||||
# to avoid the collision.
|
||||
# Reject members that clash when mapped to C names (we would have two 'a_b'
|
||||
# members).
|
||||
{ 'command': 'oops', 'data': { 'a-b': 'str', 'a_b': 'str' } }
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
object :empty
|
||||
object :obj-oops-arg
|
||||
member a-b: str optional=False
|
||||
member a_b: str optional=False
|
||||
command oops :obj-oops-arg -> None
|
||||
gen=True success_response=True
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/base-cycle-direct.json:2: Object Loopy contains itself
|
|
@ -0,0 +1,2 @@
|
|||
# we reject a loop in base classes
|
||||
{ 'struct': 'Loopy', 'base': 'Loopy', 'data': {} }
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/base-cycle-indirect.json:2: Object Base1 contains itself
|
|
@ -0,0 +1,3 @@
|
|||
# we reject a loop in base classes
|
||||
{ 'struct': 'Base1', 'base': 'Base2', 'data': {} }
|
||||
{ 'struct': 'Base2', 'base': 'Base1', 'data': {} }
|
|
@ -1,2 +1,4 @@
|
|||
object :empty
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
enum Status ['good', 'bad', 'ugly']
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
object :empty
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
|
|
|
@ -1 +1 @@
|
|||
tests/qapi-schema/enum-clash-member.json:2: Enum 'MyEnum' member 'ONE' clashes with 'one'
|
||||
tests/qapi-schema/enum-clash-member.json:2: 'one_two' (member of MyEnum) collides with 'one-two' (member of MyEnum)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# we reject enums where members will clash when mapped to C enum
|
||||
{ 'enum': 'MyEnum', 'data': [ 'one', 'ONE' ] }
|
||||
{ 'enum': 'MyEnum', 'data': [ 'one-two', 'one_two' ] }
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/enum-max-member.json:3: Enum 'MyEnum' member 'max' clashes with '(automatic)'
|
|
@ -1,3 +0,0 @@
|
|||
# we reject user-supplied 'max' for clashing with implicit enum end
|
||||
# TODO: should we instead munge the implicit value to avoid the clash?
|
||||
{ 'enum': 'MyEnum', 'data': [ 'max' ] }
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/enum-member-case.json:3: 'Value' (member of NoWayThisWillGetWhitelisted) should not use uppercase
|
|
@ -0,0 +1,3 @@
|
|||
# Member names should be 'lower-case' unless the enum is whitelisted
|
||||
{ 'enum': 'UuidInfo', 'data': [ 'Value' ] } # UuidInfo is whitelisted
|
||||
{ 'enum': 'NoWayThisWillGetWhitelisted', 'data': [ 'Value' ] }
|
|
@ -1,2 +1,4 @@
|
|||
object :empty
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
event oops None
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/event-max.json:2: Event name 'MAX' cannot be created
|
|
@ -1,2 +0,0 @@
|
|||
# an event named 'MAX' would conflict with implicit C enum
|
||||
{ 'event': 'MAX' }
|
|
@ -1 +0,0 @@
|
|||
0
|
|
@ -1,18 +0,0 @@
|
|||
# Flat union branch name collision
|
||||
# FIXME: this parses, but then fails to compile due to a duplicate 'c_d'
|
||||
# (one from the base member, the other from the branch name). We should
|
||||
# either reject the collision at parse time, or munge the generated branch
|
||||
# name to allow this to compile.
|
||||
{ 'enum': 'TestEnum',
|
||||
'data': [ 'base', 'c-d' ] }
|
||||
{ 'struct': 'Base',
|
||||
'data': { 'enum1': 'TestEnum', '*c_d': 'str' } }
|
||||
{ 'struct': 'Branch1',
|
||||
'data': { 'string': 'str' } }
|
||||
{ 'struct': 'Branch2',
|
||||
'data': { 'value': 'int' } }
|
||||
{ 'union': 'TestUnion',
|
||||
'base': 'Base',
|
||||
'discriminator': 'enum1',
|
||||
'data': { 'base': 'Branch1',
|
||||
'c-d': 'Branch2' } }
|
|
@ -1,14 +0,0 @@
|
|||
object :empty
|
||||
object Base
|
||||
member enum1: TestEnum optional=False
|
||||
member c_d: str optional=True
|
||||
object Branch1
|
||||
member string: str optional=False
|
||||
object Branch2
|
||||
member value: int optional=False
|
||||
enum TestEnum ['base', 'c-d']
|
||||
object TestUnion
|
||||
base Base
|
||||
tag enum1
|
||||
case base: Branch1
|
||||
case c-d: Branch2
|
|
@ -1 +1 @@
|
|||
tests/qapi-schema/flat-union-clash-member.json:11: Member name 'name' of branch 'value1' clashes with base 'Base'
|
||||
tests/qapi-schema/flat-union-clash-member.json:11: 'name' (member of Branch1) collides with 'name' (member of Base)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/flat-union-clash-type.json:11: Discriminator name 'type' collides with enum value in 'TestEnum'
|
|
@ -1,14 +0,0 @@
|
|||
# Flat union branch 'type'
|
||||
# Reject this, because we would have a clash in generated C, between the
|
||||
# outer tag 'type' and the branch name 'type' within the union.
|
||||
# TODO: We could munge the generated C branch name to let it compile.
|
||||
{ 'enum': 'TestEnum',
|
||||
'data': [ 'type' ] }
|
||||
{ 'struct': 'Base',
|
||||
'data': { 'type': 'TestEnum' } }
|
||||
{ 'struct': 'Branch1',
|
||||
'data': { 'string': 'str' } }
|
||||
{ 'union': 'TestUnion',
|
||||
'base': 'Base',
|
||||
'discriminator': 'type',
|
||||
'data': { 'type': 'Branch1' } }
|
|
@ -2,6 +2,8 @@ object :empty
|
|||
object Base
|
||||
member type: Empty optional=False
|
||||
enum Empty []
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
object Union
|
||||
base Base
|
||||
tag type
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
object :empty
|
||||
object :obj-fooA-arg
|
||||
member bar1: str optional=False
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
command fooA :obj-fooA-arg -> None
|
||||
gen=True success_response=True
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
object :empty
|
||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
||||
prefix QTYPE
|
||||
enum Status ['good', 'bad', 'ugly']
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue