diff options
59 files changed, 500 insertions, 157 deletions
@@ -31,19 +31,6 @@ printf " '%s'" "$0" "$@" >> config.log echo >> config.log echo "#" >> config.log -# Save the configure command line for later reuse. -cat <<EOD >config.status -#!/bin/sh -# Generated by configure. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. -EOD -printf "exec" >>config.status -printf " '%s'" "$0" "$@" >>config.status -echo >>config.status -chmod +x config.status - error_exit() { echo echo "ERROR: $1" @@ -5146,3 +5133,17 @@ done if test "$docs" = "yes" ; then mkdir -p QMP fi + +# Save the configure command line for later reuse. +cat <<EOD >config.status +#!/bin/sh +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. +EOD +printf "exec" >>config.status +printf " '%s'" "$0" "$@" >>config.status +echo >>config.status +chmod +x config.status + diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 0728f36c65..d78921f875 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -123,11 +123,12 @@ And it looks like this on the wire: Flat union types avoid the nesting on the wire. They are used whenever a specific field of the base type is declared as the discriminator ('type' is -then no longer generated). The discriminator must always be a string field. +then no longer generated). The discriminator must be of enumeration type. The above example can then be modified as follows: + { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] } { 'type': 'BlockdevCommonOptions', - 'data': { 'driver': 'str', 'readonly': 'bool' } } + 'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } } { 'union': 'BlockdevOptions', 'base': 'BlockdevCommonOptions', 'discriminator': 'driver', diff --git a/hw/core/loader.c b/hw/core/loader.c index b323c0c7b8..2bf6b8ff85 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -54,7 +54,8 @@ #include <zlib.h> -bool rom_file_in_ram = true; +bool option_rom_has_mr = false; +bool rom_file_has_mr = true; static int roms_loaded; @@ -642,7 +643,8 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name) } int rom_add_file(const char *file, const char *fw_dir, - hwaddr addr, int32_t bootindex) + hwaddr addr, int32_t bootindex, + bool option_rom) { Rom *rom; int rc, fd = -1; @@ -694,7 +696,7 @@ int rom_add_file(const char *file, const char *fw_dir, basename); snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); - if (rom_file_in_ram) { + if ((!option_rom || option_rom_has_mr) && rom_file_has_mr) { data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); } else { data = rom->data; @@ -738,7 +740,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len, snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); - if (rom_file_in_ram) { + if (rom_file_has_mr) { data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); } else { data = rom->data; @@ -773,12 +775,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize, int rom_add_vga(const char *file) { - return rom_add_file(file, "vgaroms", 0, -1); + return rom_add_file(file, "vgaroms", 0, -1, true); } int rom_add_option(const char *file, int32_t bootindex) { - return rom_add_file(file, "genroms", 0, bootindex); + return rom_add_file(file, "genroms", 0, bootindex, true); } static void rom_reset(void *unused) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b667d31de5..7ecfd7004b 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -466,9 +466,15 @@ static void acpi_align_size(GArray *blob, unsigned align) g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); } -/* Get pointer within table in a safe manner */ -#define ACPI_BUILD_PTR(table, size, off, type) \ - ((type *)(acpi_data_get_ptr(table, size, off, sizeof(type)))) +/* Set a value within table in a safe manner */ +#define ACPI_BUILD_SET_LE(table, size, off, bits, val) \ + do { \ + uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \ + memcpy(acpi_data_get_ptr(table, size, off, \ + (bits) / BITS_PER_BYTE), \ + &ACPI_BUILD_SET_LE_val, \ + (bits) / BITS_PER_BYTE); \ + } while (0) static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size, unsigned off, unsigned size) @@ -974,22 +980,17 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state) static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size) { - *ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) = - cpu_to_le32(pci->w32.begin); + ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin); - *ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) = - cpu_to_le32(pci->w32.end - 1); + ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1); if (pci->w64.end || pci->w64.begin) { - *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1; - *ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) = - cpu_to_le64(pci->w64.begin); - *ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) = - cpu_to_le64(pci->w64.end - 1); - *ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) = - cpu_to_le64(pci->w64.end - pci->w64.begin); + ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1); + ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin); + ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1); + ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin); } else { - *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0; + ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0); } } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index ae1699d6db..5e1d2d3de3 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -266,13 +266,14 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args) { smbios_type1_defaults = false; gigabyte_align = false; + option_rom_has_mr = true; } static void pc_compat_1_6(QEMUMachineInitArgs *args) { pc_compat_1_7(args); has_pci_info = false; - rom_file_in_ram = false; + rom_file_has_mr = false; has_acpi_build = false; } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index a7f626096a..4b0456a95b 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -244,13 +244,14 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args) { smbios_type1_defaults = false; gigabyte_align = false; + option_rom_has_mr = true; } static void pc_compat_1_6(QEMUMachineInitArgs *args) { pc_compat_1_7(args); has_pci_info = false; - rom_file_in_ram = false; + rom_file_has_mr = false; has_acpi_build = false; } diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 4bc2e0118e..8b8cc4e294 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -272,7 +272,7 @@ static void mch_update_smram(MCHPCIState *mch) PCIDevice *pd = PCI_DEVICE(mch); memory_region_transaction_begin(); - smram_update(&mch->smram_region, pd->config[MCH_HOST_BRDIGE_SMRAM], + smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM], mch->smm_enabled); memory_region_transaction_commit(); } @@ -283,7 +283,7 @@ static void mch_set_smm(int smm, void *arg) PCIDevice *pd = PCI_DEVICE(mch); memory_region_transaction_begin(); - smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRDIGE_SMRAM], + smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM], &mch->smram_region); memory_region_transaction_commit(); } @@ -306,8 +306,8 @@ static void mch_write_config(PCIDevice *d, mch_update_pciexbar(mch); } - if (ranges_overlap(address, len, MCH_HOST_BRDIGE_SMRAM, - MCH_HOST_BRDIGE_SMRAM_SIZE)) { + if (ranges_overlap(address, len, MCH_HOST_BRIDGE_SMRAM, + MCH_HOST_BRIDGE_SMRAM_SIZE)) { mch_update_smram(mch); } } @@ -347,7 +347,7 @@ static void mch_reset(DeviceState *qdev) pci_set_quad(d->config + MCH_HOST_BRIDGE_PCIEXBAR, MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT); - d->config[MCH_HOST_BRDIGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; + d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT; mch_update(mch); } diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h index 9e4a0e4b8d..e19143555e 100644 --- a/include/hw/i386/ich9.h +++ b/include/hw/i386/ich9.h @@ -102,7 +102,7 @@ Object *ich9_lpc_find(void); #define ICH9_USB_UHCI1_DEV 29 #define ICH9_USB_UHCI1_FUNC 0 -/* D30:F0 DMI-to-PCI brdige */ +/* D30:F0 DMI-to-PCI bridge */ #define ICH9_D2P_BRIDGE "ICH9 D2P BRIDGE" #define ICH9_D2P_BRIDGE_SAVEVM_VERSION 0 diff --git a/include/hw/loader.h b/include/hw/loader.h index aaf08c377e..796cbf9b39 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -49,10 +49,12 @@ void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size, const char *source); -extern bool rom_file_in_ram; +extern bool option_rom_has_mr; +extern bool rom_file_has_mr; int rom_add_file(const char *file, const char *fw_dir, - hwaddr addr, int32_t bootindex); + hwaddr addr, int32_t bootindex, + bool option_rom); void *rom_add_blob(const char *name, const void *blob, size_t len, hwaddr addr, const char *fw_file_name, FWCfgReadCallback fw_callback, void *callback_opaque); @@ -66,7 +68,7 @@ void *rom_ptr(hwaddr addr); void do_info_roms(Monitor *mon, const QDict *qdict); #define rom_add_file_fixed(_f, _a, _i) \ - rom_add_file(_f, NULL, _a, _i) + rom_add_file(_f, NULL, _a, _i, false) #define rom_add_blob_fixed(_f, _b, _l, _a) \ rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index d0355b712b..d9ee97845b 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -125,8 +125,8 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_PAM_RE ((uint8_t)0x1) #define MCH_HOST_BRIDGE_PAM_MASK ((uint8_t)0x3) -#define MCH_HOST_BRDIGE_SMRAM 0x9d -#define MCH_HOST_BRDIGE_SMRAM_SIZE 1 +#define MCH_HOST_BRIDGE_SMRAM 0x9d +#define MCH_HOST_BRIDGE_SMRAM_SIZE 1 #define MCH_HOST_BRIDGE_SMRAM_DEFAULT ((uint8_t)0x2) #define MCH_HOST_BRIDGE_SMRAM_D_OPEN ((uint8_t)(1 << 6)) #define MCH_HOST_BRIDGE_SMRAM_D_CLS ((uint8_t)(1 << 5)) @@ -140,16 +140,16 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_UPPER_SYSTEM_BIOS_END 0x100000 #define MCH_HOST_BRIDGE_ESMRAMC 0x9e -#define MCH_HOST_BRDIGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 6)) -#define MCH_HOST_BRDIGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 5)) -#define MCH_HOST_BRDIGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 4)) -#define MCH_HOST_BRDIGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 3)) -#define MCH_HOST_BRDIGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 2)) -#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_MASK ((uint8_t)(0x3 << 1)) -#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_1MB ((uint8_t)(0x0 << 1)) -#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_2MB ((uint8_t)(0x1 << 1)) -#define MCH_HOST_BRDIGE_ESMRAMC_TSEG_SZ_8MB ((uint8_t)(0x2 << 1)) -#define MCH_HOST_BRDIGE_ESMRAMC_T_EN ((uint8_t)1) +#define MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME ((uint8_t)(1 << 6)) +#define MCH_HOST_BRIDGE_ESMRAMC_E_SMERR ((uint8_t)(1 << 5)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_CACHE ((uint8_t)(1 << 4)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L1 ((uint8_t)(1 << 3)) +#define MCH_HOST_BRIDGE_ESMRAMC_SM_L2 ((uint8_t)(1 << 2)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK ((uint8_t)(0x3 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB ((uint8_t)(0x0 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB ((uint8_t)(0x1 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB ((uint8_t)(0x2 << 1)) +#define MCH_HOST_BRIDGE_ESMRAMC_T_EN ((uint8_t)1) /* D1:F0 PCIE* port*/ #define MCH_PCIE_DEV 1 diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 25193c943b..da75abf6d6 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -159,7 +159,7 @@ void qerror_report_err(Error *err); ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" #define QERR_KVM_MISSING_CAP \ - ERROR_CLASS_K_V_M_MISSING_CAP, "Using KVM without %s, %s unavailable" + ERROR_CLASS_KVM_MISSING_CAP, "Using KVM without %s, %s unavailable" #define QERR_MIGRATION_ACTIVE \ ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" diff --git a/qapi-schema.json b/qapi-schema.json index 6c381b7306..f4f9439fe6 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4249,6 +4249,18 @@ '*no-flush': 'bool' } } ## +# @BlockdevDriver +# +# Drivers that are supported in block device operations. +# +# Since: 2.0 +## +{ 'enum': 'BlockdevDriver', + 'data': [ 'file', 'http', 'https', 'ftp', 'ftps', 'tftp', 'vvfat', 'blkdebug', + 'blkverify', 'bochs', 'cloop', 'cow', 'dmg', 'parallels', 'qcow', + 'qcow2', 'qed', 'raw', 'vdi', 'vhdx', 'vmdk', 'vpc', 'quorum' ] } + +## # @BlockdevOptionsBase # # Options that are available for all block devices, independent of the block @@ -4272,7 +4284,7 @@ # Since: 1.7 ## { 'type': 'BlockdevOptionsBase', - 'data': { 'driver': 'str', + 'data': { 'driver': 'BlockdevDriver', '*id': 'str', '*node-name': 'str', '*discard': 'BlockdevDiscardOptions', diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 2c6e0dcd5c..10864efc58 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -127,16 +127,6 @@ const char *%(name)s_lookup[] = { ''') return ret -def generate_enum_name(name): - if name.isupper(): - return c_fun(name, False) - new_name = '' - for c in c_fun(name, False): - if c.isupper(): - new_name += '_' - new_name += c - return new_name.lstrip('_').upper() - def generate_enum(name, values): lookup_decl = mcgen(''' extern const char *%(name)s_lookup[]; @@ -154,11 +144,11 @@ typedef enum %(name)s i = 0 for value in enum_values: + enum_full_value = generate_enum_full_value(name, value) enum_decl += mcgen(''' - %(abbrev)s_%(value)s = %(i)d, + %(enum_full_value)s = %(i)d, ''', - abbrev=de_camel_case(name).upper(), - value=generate_enum_name(value), + enum_full_value = enum_full_value, i=i) i += 1 @@ -211,14 +201,21 @@ def generate_union(expr): base = expr.get('base') discriminator = expr.get('discriminator') + enum_define = discriminator_find_enum_define(expr) + if enum_define: + discriminator_type_name = enum_define['enum_name'] + else: + discriminator_type_name = '%sKind' % (name) + ret = mcgen(''' struct %(name)s { - %(name)sKind kind; + %(discriminator_type_name)s kind; union { void *data; ''', - name=name) + name=name, + discriminator_type_name=discriminator_type_name) for key in typeinfo: ret += mcgen(''' @@ -399,8 +396,11 @@ for expr in exprs: fdef.write(generate_enum_lookup(expr['enum'], expr['data'])) elif expr.has_key('union'): ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" - ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) - fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) + enum_define = discriminator_find_enum_define(expr) + if not enum_define: + ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) + fdef.write(generate_enum_lookup('%sKind' % expr['union'], + expr['data'].keys())) if expr.get('discriminator') == {}: fdef.write(generate_anon_union_qtypes(expr)) else: diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index c6de9aeed4..45ce3a957a 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -214,18 +214,22 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** ''', name=name) + # For anon union, always use the default enum type automatically generated + # as "'%sKind' % (name)" + disc_type = '%sKind' % (name) + for key in members: assert (members[key] in builtin_types or find_struct(members[key]) or find_union(members[key])), "Invalid anonymous union member" + enum_full_value = generate_enum_full_value(disc_type, key) ret += mcgen(''' - case %(abbrev)s_KIND_%(enum)s: + case %(enum_full_value)s: visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); break; ''', - abbrev = de_camel_case(name).upper(), - enum = c_fun(de_camel_case(key),False).upper(), + enum_full_value = enum_full_value, c_type = type_name(members[key]), c_name = c_fun(key)) @@ -255,7 +259,16 @@ def generate_visit_union(expr): assert not base return generate_visit_anon_union(name, members) - ret = generate_visit_enum('%sKind' % name, members.keys()) + enum_define = discriminator_find_enum_define(expr) + if enum_define: + # Use the enum type as discriminator + ret = "" + disc_type = enum_define['enum_name'] + else: + # There will always be a discriminator in the C switch code, by default it + # is an enum type generated silently as "'%sKind' % (name)" + ret = generate_visit_enum('%sKind' % name, members.keys()) + disc_type = '%sKind' % (name) if base: base_fields = find_struct(base)['data'] @@ -291,15 +304,16 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** pop_indent() if not discriminator: - desc_type = "type" + disc_key = "type" else: - desc_type = discriminator + disc_key = discriminator ret += mcgen(''' - visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err); + visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err); if (!err) { switch ((*obj)->kind) { ''', - name=name, type=desc_type) + disc_type = disc_type, + disc_key = disc_key) for key in members: if not discriminator: @@ -313,13 +327,13 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** visit_end_implicit_struct(m, &err); }''' + enum_full_value = generate_enum_full_value(disc_type, key) ret += mcgen(''' - case %(abbrev)s_KIND_%(enum)s: + case %(enum_full_value)s: ''' + fmt + ''' break; ''', - abbrev = de_camel_case(name).upper(), - enum = c_fun(de_camel_case(key),False).upper(), + enum_full_value = enum_full_value, c_type=type_name(members[key]), c_name=c_fun(key)) @@ -510,7 +524,11 @@ for expr in exprs: ret += generate_visit_list(expr['union'], expr['data']) fdef.write(ret) - ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys()) + enum_define = discriminator_find_enum_define(expr) + ret = "" + if not enum_define: + ret = generate_decl_enum('%sKind' % expr['union'], + expr['data'].keys()) ret += generate_declaration(expr['union'], expr['data']) fdecl.write(ret) elif expr.has_key('enum'): diff --git a/scripts/qapi.py b/scripts/qapi.py index f3c2a2037a..b474c39558 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -39,12 +39,10 @@ class QAPISchemaError(Exception): def __init__(self, schema, msg): self.fp = schema.fp self.msg = msg - self.line = self.col = 1 - for ch in schema.src[0:schema.pos]: - if ch == '\n': - self.line += 1 - self.col = 1 - elif ch == '\t': + self.col = 1 + self.line = schema.line + for ch in schema.src[schema.line_pos:schema.pos]: + if ch == '\t': self.col = (self.col + 7) % 8 + 1 else: self.col += 1 @@ -52,6 +50,15 @@ class QAPISchemaError(Exception): def __str__(self): return "%s:%s:%s: %s" % (self.fp.name, self.line, self.col, self.msg) +class QAPIExprError(Exception): + def __init__(self, expr_info, msg): + self.fp = expr_info['fp'] + self.line = expr_info['line'] + self.msg = msg + + def __str__(self): + return "%s:%s: %s" % (self.fp.name, self.line, self.msg) + class QAPISchema: def __init__(self, fp): @@ -60,11 +67,16 @@ class QAPISchema: if self.src == '' or self.src[-1] != '\n': self.src += '\n' self.cursor = 0 + self.line = 1 + self.line_pos = 0 self.exprs = [] self.accept() while self.tok != None: - self.exprs.append(self.get_expr(False)) + expr_info = {'fp': fp, 'line': self.line} + expr_elem = {'expr': self.get_expr(False), + 'info': expr_info} + self.exprs.append(expr_elem) def accept(self): while True: @@ -100,6 +112,8 @@ class QAPISchema: if self.cursor == len(self.src): self.tok = None return + self.line += 1 + self.line_pos = self.cursor elif not self.tok.isspace(): raise QAPISchemaError(self, 'Stray "%s"' % self.tok) @@ -116,6 +130,8 @@ class QAPISchema: if self.tok != ':': raise QAPISchemaError(self, 'Expected ":"') self.accept() + if key in expr: + raise QAPISchemaError(self, 'Duplicate key "%s"' % key) expr[key] = self.get_expr(True) if self.tok == '}': self.accept() @@ -158,6 +174,95 @@ class QAPISchema: raise QAPISchemaError(self, 'Expected "{", "[" or string') return expr +def find_base_fields(base): + base_struct_define = find_struct(base) + if not base_struct_define: + return None + return base_struct_define['data'] + +# Return the discriminator enum define if discriminator is specified as an +# enum type, otherwise return None. +def discriminator_find_enum_define(expr): + base = expr.get('base') + discriminator = expr.get('discriminator') + + if not (discriminator and base): + return None + + base_fields = find_base_fields(base) + if not base_fields: + return None + + discriminator_type = base_fields.get(discriminator) + if not discriminator_type: + return None + + return find_enum(discriminator_type) + +def check_union(expr, expr_info): + name = expr['union'] + base = expr.get('base') + discriminator = expr.get('discriminator') + members = expr['data'] + + # If the object has a member 'base', its value must name a complex type. + if base: + base_fields = find_base_fields(base) + if not base_fields: + raise QAPIExprError(expr_info, + "Base '%s' is not a valid type" + % base) + + # If the union object has no member 'discriminator', it's an + # ordinary union. + if not discriminator: + enum_define = None + + # Else if the value of member 'discriminator' is {}, it's an + # anonymous union. + elif discriminator == {}: + enum_define = None + + # Else, it's a flat union. + else: + # The object must have a member 'base'. + if not base: + raise QAPIExprError(expr_info, + "Flat union '%s' must have a base field" + % name) + # The value of member 'discriminator' must name a member of the + # base type. + discriminator_type = base_fields.get(discriminator) + if not discriminator_type: + raise QAPIExprError(expr_info, + "Discriminator '%s' is not a member of base " + "type '%s'" + % (discriminator, base)) + enum_define = find_enum(discriminator_type) + # Do not allow string discriminator + if not enum_define: + raise QAPIExprError(expr_info, + "Discriminator '%s' must be of enumeration " + "type" % discriminator) + + # Check every branch + for (key, value) in members.items(): + # If this named member's value names an enum type, then all members + # of 'data' must also be members of the enum type. + if enum_define and not key in enum_define['enum_values']: + raise QAPIExprError(expr_info, + "Discriminator value '%s' is not found in " + "enum '%s'" % + (key, enum_define["enum_name"])) + # Todo: add checking for values. Key is checked as above, value can be + # also checked here, but we need more functions to handle array case. + +def check_exprs(schema): + for expr_elem in schema.exprs: + expr = expr_elem['expr'] + if expr.has_key('union'): + check_union(expr, expr_elem['info']) + def parse_schema(fp): try: schema = QAPISchema(fp) @@ -167,16 +272,29 @@ def parse_schema(fp): exprs = [] - for expr in schema.exprs: + for expr_elem in schema.exprs: + expr = expr_elem['expr'] if expr.has_key('enum'): - add_enum(expr['enum']) + add_enum(expr['enum'], expr['data']) elif expr.has_key('union'): add_union(expr) - add_enum('%sKind' % expr['union']) elif expr.has_key('type'): add_struct(expr) exprs.append(expr) + # Try again for hidden UnionKind enum + for expr_elem in schema.exprs: + expr = expr_elem['expr'] + if expr.has_key('union'): + if not discriminator_find_enum_define(expr): + add_enum('%sKind' % expr['union']) + + try: + check_exprs(schema) + except QAPIExprError, e: + print >>sys.stderr, e + exit(1) + return exprs def parse_args(typeinfo): @@ -289,13 +407,19 @@ def find_union(name): return union return None -def add_enum(name): +def add_enum(name, enum_values = None): global enum_types - enum_types.append(name) + enum_types.append({"enum_name": name, "enum_values": enum_values}) -def is_enum(name): +def find_enum(name): global enum_types - return (name in enum_types) + for enum in enum_types: + if enum['enum_name'] == name: + return enum + return None + +def is_enum(name): + return find_enum(name) != None def c_type(name): if name == 'str': @@ -373,3 +497,30 @@ def guardend(name): ''', name=guardname(name)) + +# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1 +# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2 +# ENUM24_Name -> ENUM24_NAME +def _generate_enum_string(value): + c_fun_str = c_fun(value, False) + if value.isupper(): + return c_fun_str + + new_name = '' + l = len(c_fun_str) + for i in range(l): + c = c_fun_str[i] + # When c is upper and no "_" appears before, do more checks + if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_": + # Case 1: next string is lower + # Case 2: previous string is digit + if (i < (l - 1) and c_fun_str[i + 1].islower()) or \ + c_fun_str[i - 1].isdigit(): + new_name += '_' + new_name += c + return new_name.lstrip('_').upper() + +def generate_enum_full_value(enum_name, enum_value): + abbrev_string = _generate_enum_string(enum_name) + value_string = _generate_enum_string(enum_value) + return "%s_%s" % (abbrev_string, value_string) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 9f69d7e192..5cfe4506e0 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -315,7 +315,7 @@ typedef struct X86RegisterInfo32 { } X86RegisterInfo32; #define REGISTER(reg) \ - [R_##reg] = { .name = #reg, .qapi_enum = X86_C_P_U_REGISTER32_##reg } + [R_##reg] = { .name = #reg, .qapi_enum = X86_CPU_REGISTER32_##reg } X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { REGISTER(EAX), REGISTER(ECX), diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index e7f878ee81..5806e59af3 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -458,7 +458,8 @@ static const sparc_def_t sparc_defs[] = { .mmu_trcr_mask = 0xffffffff, .nwindows = 8, .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN | - CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN, + CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN | + CPU_FEATURE_CASA, }, #endif }; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index c519063ba9..ed6d2d1204 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -271,6 +271,7 @@ typedef struct sparc_def_t { #define CPU_FEATURE_ASR17 (1 << 15) #define CPU_FEATURE_CACHE_CTRL (1 << 16) #define CPU_FEATURE_POWERDOWN (1 << 17) +#define CPU_FEATURE_CASA (1 << 18) #ifndef TARGET_SPARC64 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \ @@ -282,7 +283,8 @@ typedef struct sparc_def_t { CPU_FEATURE_MUL | CPU_FEATURE_DIV | \ CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \ CPU_FEATURE_FMUL | CPU_FEATURE_VIS1 | \ - CPU_FEATURE_VIS2 | CPU_FEATURE_FSMULD) + CPU_FEATURE_VIS2 | CPU_FEATURE_FSMULD | \ + CPU_FEATURE_CASA) enum { mmu_us_12, // Ultrasparc < III (64 entry TLB) mmu_us_3, // Ultrasparc III (512 entry TLB) diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 2a771b2093..cd8d3fa9f4 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -22,7 +22,6 @@ DEF_HELPER_1(popc, tl, tl) DEF_HELPER_4(ldda_asi, void, env, tl, int, int) DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int) DEF_HELPER_5(stf_asi, void, env, tl, int, int, int) -DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32) DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32) DEF_HELPER_2(set_softint, void, env, i64) DEF_HELPER_2(clear_softint, void, env, i64) @@ -31,6 +30,9 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64) DEF_HELPER_1(tick_get_count, i64, ptr) DEF_HELPER_2(tick_set_limit, void, ptr, i64) #endif +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) +DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32) +#endif DEF_HELPER_3(check_align, void, env, tl, i32) DEF_HELPER_1(debug, void, env) DEF_HELPER_1(save, void, env) diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 92761ad17b..32491b499a 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -584,6 +584,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size, } break; case 0xb: /* Supervisor data access */ + case 0x80: switch (size) { case 1: ret = cpu_ldub_kernel(env, addr); @@ -955,6 +956,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi, } break; case 0xb: /* Supervisor data access */ + case 0x80: switch (size) { case 1: cpu_stb_kernel(env, addr, val); @@ -2232,33 +2234,35 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size, } } -target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr, - target_ulong val1, target_ulong val2, uint32_t asi) +target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr, + target_ulong val1, target_ulong val2, + uint32_t asi) { target_ulong ret; - val2 &= 0xffffffffUL; - ret = helper_ld_asi(env, addr, asi, 4, 0); - ret &= 0xffffffffUL; + ret = helper_ld_asi(env, addr, asi, 8, 0); if (val2 == ret) { - helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4); + helper_st_asi(env, addr, val1, asi, 8); } return ret; } +#endif /* TARGET_SPARC64 */ -target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr, - target_ulong val1, target_ulong val2, - uint32_t asi) +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) +target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr, + target_ulong val1, target_ulong val2, uint32_t asi) { target_ulong ret; - ret = helper_ld_asi(env, addr, asi, 8, 0); + val2 &= 0xffffffffUL; + ret = helper_ld_asi(env, addr, asi, 4, 0); + ret &= 0xffffffffUL; if (val2 == ret) { - helper_st_asi(env, addr, val1, asi, 8); + helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4); } return ret; } -#endif /* TARGET_SPARC64 */ +#endif /* !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) */ void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx) { diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 6150b22f8f..46d7859e97 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2107,18 +2107,6 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, tcg_temp_free_i64(t64); } -static inline void gen_cas_asi(DisasContext *dc, TCGv addr, - TCGv val2, int insn, int rd) -{ - TCGv val1 = gen_load_gpr(dc, rd); - TCGv dst = gen_dest_gpr(dc, rd); - TCGv_i32 r_asi = gen_get_asi(insn, addr); - - gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi); - tcg_temp_free_i32(r_asi); - gen_store_gpr(dc, rd, dst); -} - static inline void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv val2, int insn, int rd) { @@ -2229,6 +2217,22 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, #endif #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) +static inline void gen_cas_asi(DisasContext *dc, TCGv addr, + TCGv val2, int insn, int rd) +{ + TCGv val1 = gen_load_gpr(dc, rd); + TCGv dst = gen_dest_gpr(dc, rd); +#ifdef TARGET_SPARC64 + TCGv_i32 r_asi = gen_get_asi(insn, addr); +#else + TCGv_i32 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26)); +#endif + + gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi); + tcg_temp_free_i32(r_asi); + gen_store_gpr(dc, rd, dst); +} + static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn) { TCGv_i64 r_val; @@ -5103,11 +5107,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); break; - case 0x3c: /* V9 casa */ - rs2 = GET_FIELD(insn, 27, 31); - cpu_src2 = gen_load_gpr(dc, rs2); - gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); - break; case 0x3e: /* V9 casxa */ rs2 = GET_FIELD(insn, 27, 31); cpu_src2 = gen_load_gpr(dc, rs2); @@ -5120,6 +5119,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) case 0x37: /* stdc */ goto ncp_insn; #endif +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) + case 0x3c: /* V9 or LEON3 casa */ +#ifndef TARGET_SPARC64 + CHECK_IU_FEATURE(dc, CASA); + if (IS_IMM) { + goto illegal_insn; + } + if (!supervisor(dc)) { + goto priv_insn; + } +#endif + rs2 = GET_FIELD(insn, 27, 31); + cpu_src2 = gen_load_gpr(dc, rs2); + gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); + break; +#endif default: goto illegal_insn; } diff --git a/tests/Makefile b/tests/Makefile index b17d41e4e2..e146f81d44 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -142,7 +142,11 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ missing-comma-object.json non-objects.json \ qapi-schema-test.json quoted-structural-chars.json \ trailing-comma-list.json trailing-comma-object.json \ - unclosed-list.json unclosed-object.json unclosed-string.json) + unclosed-list.json unclosed-object.json unclosed-string.json \ + duplicate-key.json union-invalid-base.json flat-union-no-base.json \ + flat-union-invalid-discriminator.json \ + flat-union-invalid-branch-key.json flat-union-reverse-define.json \ + flat-union-string-discriminator.json) GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT Binary files differindex c1a4589db0..ae5a9a57d6 100644 --- a/tests/acpi-test-data/pc/SSDT +++ b/tests/acpi-test-data/pc/SSDT diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT Binary files differindex 9915dbe5b1..634b4817fc 100644 --- a/tests/acpi-test-data/q35/SSDT +++ b/tests/acpi-test-data/q35/SSDT diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out index e3bd904453..4ce3dcf12f 100644 --- a/tests/qapi-schema/comments.out +++ b/tests/qapi-schema/comments.out @@ -1,3 +1,3 @@ [OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])] -['Status'] +[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}] [] diff --git a/tests/qapi-schema/duplicate-key.err b/tests/qapi-schema/duplicate-key.err new file mode 100644 index 0000000000..0801c6a9bb --- /dev/null +++ b/tests/qapi-schema/duplicate-key.err @@ -0,0 +1 @@ +<stdin>:2:10: Duplicate key "key" diff --git a/tests/qapi-schema/duplicate-key.exit b/tests/qapi-schema/duplicate-key.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/duplicate-key.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/duplicate-key.json b/tests/qapi-schema/duplicate-key.json new file mode 100644 index 0000000000..1b55d88107 --- /dev/null +++ b/tests/qapi-schema/duplicate-key.json @@ -0,0 +1,2 @@ +{ 'key': 'value', + 'key': 'value' } diff --git a/tests/qapi-schema/duplicate-key.out b/tests/qapi-schema/duplicate-key.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/duplicate-key.out diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.err b/tests/qapi-schema/flat-union-invalid-branch-key.err new file mode 100644 index 0000000000..1125caf5db --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-branch-key.err @@ -0,0 +1 @@ +<stdin>:13: Discriminator value 'value_wrong' is not found in enum 'TestEnum' diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.exit b/tests/qapi-schema/flat-union-invalid-branch-key.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-branch-key.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.json b/tests/qapi-schema/flat-union-invalid-branch-key.json new file mode 100644 index 0000000000..a6242823ed --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-branch-key.json @@ -0,0 +1,17 @@ +{ 'enum': 'TestEnum', + 'data': [ 'value1', 'value2' ] } + +{ 'type': 'TestBase', + 'data': { 'enum1': 'TestEnum' } } + +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } + +{ 'union': 'TestUnion', + 'base': 'TestBase', + 'discriminator': 'enum1', + 'data': { 'value_wrong': 'TestTypeA', + 'value2': 'TestTypeB' } } diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.out b/tests/qapi-schema/flat-union-invalid-branch-key.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-branch-key.out diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.err b/tests/qapi-schema/flat-union-invalid-discriminator.err new file mode 100644 index 0000000000..cad9dbf225 --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-discriminator.err @@ -0,0 +1 @@ +<stdin>:13: Discriminator 'enum_wrong' is not a member of base type 'TestBase' diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.exit b/tests/qapi-schema/flat-union-invalid-discriminator.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-discriminator.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.json b/tests/qapi-schema/flat-union-invalid-discriminator.json new file mode 100644 index 0000000000..887157e173 --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-discriminator.json @@ -0,0 +1,17 @@ +{ 'enum': 'TestEnum', + 'data': [ 'value1', 'value2' ] } + +{ 'type': 'TestBase', + 'data': { 'enum1': 'TestEnum' } } + +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } + +{ 'union': 'TestUnion', + 'base': 'TestBase', + 'discriminator': 'enum_wrong', + 'data': { 'value1': 'TestTypeA', + 'value2': 'TestTypeB' } } diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.out b/tests/qapi-schema/flat-union-invalid-discriminator.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/flat-union-invalid-discriminator.out diff --git a/tests/qapi-schema/flat-union-no-base.err b/tests/qapi-schema/flat-union-no-base.err new file mode 100644 index 0000000000..e2d7443a3b --- /dev/null +++ b/tests/qapi-schema/flat-union-no-base.err @@ -0,0 +1 @@ +<stdin>:7: Flat union 'TestUnion' must have a base field diff --git a/tests/qapi-schema/flat-union-no-base.exit b/tests/qapi-schema/flat-union-no-base.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/flat-union-no-base.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/flat-union-no-base.json b/tests/qapi-schema/flat-union-no-base.json new file mode 100644 index 0000000000..50f267323b --- /dev/null +++ b/tests/qapi-schema/flat-union-no-base.json @@ -0,0 +1,10 @@ +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } + +{ 'union': 'TestUnion', + 'discriminator': 'enum1', + 'data': { 'value1': 'TestTypeA', + 'value2': 'TestTypeB' } } diff --git a/tests/qapi-schema/flat-union-no-base.out b/tests/qapi-schema/flat-union-no-base.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/flat-union-no-base.out diff --git a/tests/qapi-schema/flat-union-reverse-define.err b/tests/qapi-schema/flat-union-reverse-define.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/flat-union-reverse-define.err diff --git a/tests/qapi-schema/flat-union-reverse-define.exit b/tests/qapi-schema/flat-union-reverse-define.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/flat-union-reverse-define.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/flat-union-reverse-define.json b/tests/qapi-schema/flat-union-reverse-define.json new file mode 100644 index 0000000000..9ea7e72201 --- /dev/null +++ b/tests/qapi-schema/flat-union-reverse-define.json @@ -0,0 +1,17 @@ +{ 'union': 'TestUnion', + 'base': 'TestBase', + 'discriminator': 'enum1', + 'data': { 'value1': 'TestTypeA', + 'value2': 'TestTypeB' } } + +{ 'type': 'TestBase', + 'data': { 'enum1': 'TestEnum' } } + +{ 'enum': 'TestEnum', + 'data': [ 'value1', 'value2' ] } + +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } diff --git a/tests/qapi-schema/flat-union-reverse-define.out b/tests/qapi-schema/flat-union-reverse-define.out new file mode 100644 index 0000000000..03c952e28a --- /dev/null +++ b/tests/qapi-schema/flat-union-reverse-define.out @@ -0,0 +1,9 @@ +[OrderedDict([('union', 'TestUnion'), ('base', 'TestBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'TestTypeA'), ('value2', 'TestTypeB')]))]), + OrderedDict([('type', 'TestBase'), ('data', OrderedDict([('enum1', 'TestEnum')]))]), + OrderedDict([('enum', 'TestEnum'), ('data', ['value1', 'value2'])]), + OrderedDict([('type', 'TestTypeA'), ('data', OrderedDict([('string', 'str')]))]), + OrderedDict([('type', 'TestTypeB'), ('data', OrderedDict([('integer', 'int')]))])] +[{'enum_name': 'TestEnum', 'enum_values': ['value1', 'value2']}] +[OrderedDict([('type', 'TestBase'), ('data', OrderedDict([('enum1', 'TestEnum')]))]), + OrderedDict([('type', 'TestTypeA'), ('data', OrderedDict([('string', 'str')]))]), + OrderedDict([('type', 'TestTypeB'), ('data', OrderedDict([('integer', 'int')]))])] diff --git a/tests/qapi-schema/flat-union-string-discriminator.err b/tests/qapi-schema/flat-union-string-discriminator.err new file mode 100644 index 0000000000..87482704ec --- /dev/null +++ b/tests/qapi-schema/flat-union-string-discriminator.err @@ -0,0 +1 @@ +<stdin>:13: Discriminator 'kind' must be of enumeration type diff --git a/tests/qapi-schema/flat-union-string-discriminator.exit b/tests/qapi-schema/flat-union-string-discriminator.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/flat-union-string-discriminator.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/flat-union-string-discriminator.json b/tests/qapi-schema/flat-union-string-discriminator.json new file mode 100644 index 0000000000..e966aeb395 --- /dev/null +++ b/tests/qapi-schema/flat-union-string-discriminator.json @@ -0,0 +1,17 @@ +{ 'enum': 'TestEnum', + 'data': [ 'value1', 'value2' ] } + +{ 'type': 'TestBase', + 'data': { 'enum1': 'TestEnum', 'kind': 'str' } } + +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } + +{ 'union': 'TestUnion', + 'base': 'TestBase', + 'discriminator': 'kind', + 'data': { 'kind1': 'TestTypeA', + 'kind2': 'TestTypeB' } } diff --git a/tests/qapi-schema/flat-union-string-discriminator.out b/tests/qapi-schema/flat-union-string-discriminator.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/flat-union-string-discriminator.out diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 471ba47dde..818c06dc75 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -37,10 +37,13 @@ 'base': 'UserDefZero', 'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } } +{ 'type': 'UserDefUnionBase', + 'data': { 'string': 'str', 'enum1': 'EnumOne' } } + { 'union': 'UserDefFlatUnion', - 'base': 'UserDefOne', - 'discriminator': 'string', - 'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } } + 'base': 'UserDefUnionBase', + 'discriminator': 'enum1', + 'data': { 'value1' : 'UserDefA', 'value2' : 'UserDefB', 'value3' : 'UserDefB' } } # FIXME generated struct UserDefFlatUnion has members for direct base # UserDefOne, but lacks members for indirect base UserDefZero diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 89b53d4d4d..6cd03f31c3 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -7,7 +7,8 @@ OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('union', 'UserDefUnion'), ('base', 'UserDefZero'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]), - OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefOne'), ('discriminator', 'string'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]), + OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), + OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]), OrderedDict([('union', 'UserDefAnonUnion'), ('discriminator', OrderedDict()), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]), OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str'])]))]), OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]), @@ -15,11 +16,10 @@ OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('*ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]), OrderedDict([('command', 'user_def_cmd3'), ('data', OrderedDict([('a', 'int'), ('*b', 'int')])), ('returns', 'int')]), OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])] -['EnumOne', - 'UserDefUnionKind', - 'UserDefFlatUnionKind', - 'UserDefAnonUnionKind', - 'UserDefNativeListUnionKind'] +[{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']}, + {'enum_name': 'UserDefUnionKind', 'enum_values': None}, + {'enum_name': 'UserDefAnonUnionKind', 'enum_values': None}, + {'enum_name': 'UserDefNativeListUnionKind', 'enum_values': None}] [OrderedDict([('type', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]), OrderedDict([('type', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('type', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]), @@ -27,4 +27,5 @@ OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]), OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), + OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])] diff --git a/tests/qapi-schema/union-invalid-base.err b/tests/qapi-schema/union-invalid-base.err new file mode 100644 index 0000000000..dd8e3d1b3b --- /dev/null +++ b/tests/qapi-schema/union-invalid-base.err @@ -0,0 +1 @@ +<stdin>:7: Base 'TestBaseWrong' is not a valid type diff --git a/tests/qapi-schema/union-invalid-base.exit b/tests/qapi-schema/union-invalid-base.exit new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/tests/qapi-schema/union-invalid-base.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/union-invalid-base.json b/tests/qapi-schema/union-invalid-base.json new file mode 100644 index 0000000000..1fa4930010 --- /dev/null +++ b/tests/qapi-schema/union-invalid-base.json @@ -0,0 +1,10 @@ +{ 'type': 'TestTypeA', + 'data': { 'string': 'str' } } + +{ 'type': 'TestTypeB', + 'data': { 'integer': 'int' } } + +{ 'union': 'TestUnion', + 'base': 'TestBaseWrong', + 'data': { 'value1': 'TestTypeA', + 'value2': 'TestTypeB' } } diff --git a/tests/qapi-schema/union-invalid-base.out b/tests/qapi-schema/union-invalid-base.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/union-invalid-base.out diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index 8e62c2d8ad..554e222b32 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -141,7 +141,7 @@ static void test_dispatch_cmd_io(void) ret3 = qobject_to_qint(test_qmp_dispatch(req)); assert(qint_get_int(ret3) == 66); - QDECREF(ret); + QDECREF(ret3); QDECREF(req); } diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c index 64d72f6f05..38b5e95f68 100644 --- a/tests/test-qmp-input-strict.c +++ b/tests/test-qmp-input-strict.c @@ -146,7 +146,10 @@ static void test_validate_union_flat(TestInputVisitorData *data, Visitor *v; Error *errp = NULL; - v = validate_test_init(data, "{ 'string': 'a', 'boolean': true }"); + v = validate_test_init(data, + "{ 'enum1': 'value1', " + "'string': 'str', " + "'boolean': true }"); /* TODO when generator bug is fixed, add 'integer': 41 */ visit_type_UserDefFlatUnion(v, &tmp, NULL, &errp); diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 2dffafc1f4..1729667a6f 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -310,14 +310,18 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, Error *err = NULL; UserDefFlatUnion *tmp; - v = visitor_input_test_init(data, "{ 'string': 'a', 'boolean': true }"); + v = visitor_input_test_init(data, + "{ 'enum1': 'value1', " + "'string': 'str', " + "'boolean': true }"); /* TODO when generator bug is fixed, add 'integer': 41 */ visit_type_UserDefFlatUnion(v, &tmp, NULL, &err); g_assert(err == NULL); - g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_A); + g_assert_cmpint(tmp->kind, ==, ENUM_ONE_VALUE1); + g_assert_cmpstr(tmp->string, ==, "str"); /* TODO g_assert_cmpint(tmp->integer, ==, 41); */ - g_assert_cmpint(tmp->a->boolean, ==, true); + g_assert_cmpint(tmp->value1->boolean, ==, true); qapi_free_UserDefFlatUnion(tmp); } diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 105f4cf94b..da279713f2 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -449,10 +449,11 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, Error *err = NULL; UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion)); - tmp->kind = USER_DEF_UNION_KIND_A; - tmp->a = g_malloc0(sizeof(UserDefA)); + tmp->kind = ENUM_ONE_VALUE1; + tmp->string = g_strdup("str"); + tmp->value1 = g_malloc0(sizeof(UserDefA)); /* TODO when generator bug is fixed: tmp->integer = 41; */ - tmp->a->boolean = true; + tmp->value1->boolean = true; visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err); g_assert(err == NULL); @@ -461,7 +462,8 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, g_assert(qobject_type(arg) == QTYPE_QDICT); qdict = qobject_to_qdict(arg); - g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "a"); + g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1"); + g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str"); /* TODO g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); */ g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true); |