diff --git a/msvc/unicorn/qapi-types.h b/msvc/unicorn/qapi-types.h index a43c5274..ea179637 100644 --- a/msvc/unicorn/qapi-types.h +++ b/msvc/unicorn/qapi-types.h @@ -154,6 +154,7 @@ void qapi_free_uint8List(uint8List *obj); #endif /* QAPI_TYPES_BUILTIN */ + typedef enum ErrorClass { ERROR_CLASS_GENERIC_ERROR = 0, ERROR_CLASS_COMMAND_NOT_FOUND = 1, @@ -170,6 +171,7 @@ typedef struct ErrorClassList ErrorClassList; typedef struct X86CPUFeatureWordInfo X86CPUFeatureWordInfo; typedef struct X86CPUFeatureWordInfoList X86CPUFeatureWordInfoList; + typedef enum X86CPURegister32 { X86_CPU_REGISTER32_EAX = 0, X86_CPU_REGISTER32_EBX = 1, diff --git a/qemu/scripts/qapi-types.py b/qemu/scripts/qapi-types.py index fa414287..8c540318 100644 --- a/qemu/scripts/qapi-types.py +++ b/qemu/scripts/qapi-types.py @@ -13,24 +13,26 @@ from qapi import * + def gen_fwd_object_or_array(name): return mcgen(''' -typedef struct %(name)s %(name)s; +typedef struct %(c_name)s %(c_name)s; ''', - name=c_name(name)) + c_name=c_name(name)) def gen_array(name, element_type): return mcgen(''' -struct %(name)s { +struct %(c_name)s { union { %(c_type)s value; uint64_t padding; }; - struct %(name)s *next; + struct %(c_name)s *next; }; ''', - name=c_name(name), c_type=element_type.c_type()) + c_name=c_name(name), c_type=element_type.c_type()) + def gen_struct_field(name, typ, optional): ret = '' @@ -46,7 +48,8 @@ def gen_struct_field(name, typ, optional): c_type=typ.c_type(), c_name=c_name(name)) return ret -def generate_struct_fields(members): + +def gen_struct_fields(members): ret = '' for memb in members: @@ -55,18 +58,19 @@ def generate_struct_fields(members): def gen_struct(name, base, members): ret = mcgen(''' -struct %(name)s { +struct %(c_name)s { ''', - name=c_name(name)) + c_name=c_name(name)) if base: ret += gen_struct_field('base', base, False) - ret += generate_struct_fields(members) + ret += gen_struct_fields(members) # 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). + # 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 not members: ret += mcgen(''' char qapi_dummy_field_for_empty_struct; @@ -78,37 +82,6 @@ struct %(name)s { return ret -def generate_enum(name, values, prefix=None): - name = c_name(name) - lookup_decl = mcgen(''' -extern const char *const %(name)s_lookup[]; -''', - name=name) - - enum_decl = mcgen(''' -typedef enum %(name)s { -''', - name=name) - - # append automatically generated _MAX value - enum_values = values + [ 'MAX' ] - - i = 0 - for value in enum_values: - enum_full_value = c_enum_const(name, value, prefix) - enum_decl += mcgen(''' - %(enum_full_value)s = %(i)d, -''', - enum_full_value = enum_full_value, - i=i) - i += 1 - - enum_decl += mcgen(''' -} %(name)s; -''', - name=name) - - return enum_decl + lookup_decl def gen_alternate_qtypes_decl(name): return mcgen(''' @@ -117,12 +90,13 @@ extern const int %(c_name)s_qtypes[]; ''', c_name=c_name(name)) + def gen_alternate_qtypes(name, variants): ret = mcgen(''' -const int %(name)s_qtypes[QTYPE_MAX] = { +const int %(c_name)s_qtypes[QTYPE_MAX] = { ''', - name=c_name(name)) + c_name=c_name(name)) for var in variants.variants: qtype = var.type.alternate_qtype() @@ -131,6 +105,7 @@ const int %(name)s_qtypes[QTYPE_MAX] = { ret += mcgen(''' [%(qtype)s] = %(enum_const)s, ''', + qtype=qtype, enum_const=c_enum_const(variants.tag_member.type.name, var.name)) @@ -142,26 +117,24 @@ const int %(name)s_qtypes[QTYPE_MAX] = { def gen_union(name, base, variants): - name = c_name(name) - ret = mcgen(''' -struct %(name)s { +struct %(c_name)s { ''', - name=name) + c_name=c_name(name)) if base: ret += mcgen(''' /* Members inherited from %(c_name)s: */ ''', c_name=c_name(base.name)) - ret += generate_struct_fields(base.members) + ret += gen_struct_fields(base.members) ret += mcgen(''' /* Own members: */ ''') else: ret += mcgen(''' - %(discriminator_type_name)s kind; + %(c_type)s kind; ''', - discriminator_type_name=c_name(variants.tag_member.type.name)) + c_type=c_name(variants.tag_member.type.name)) # 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 @@ -196,17 +169,19 @@ struct %(name)s { return ret -def generate_type_cleanup_decl(name): + +def gen_type_cleanup_decl(name): ret = mcgen(''' -void qapi_free_%(name)s(%(name)s *obj); +void qapi_free_%(c_name)s(%(c_name)s *obj); ''', - name=c_name(name)) + c_name=c_name(name)) return ret -def generate_type_cleanup(name): + +def gen_type_cleanup(name): ret = mcgen(''' -void qapi_free_%(name)s(%(name)s *obj) +void qapi_free_%(c_name)s(%(c_name)s *obj) { QapiDeallocVisitor *md; Visitor *v; @@ -217,11 +192,11 @@ void qapi_free_%(name)s(%(name)s *obj) md = qapi_dealloc_visitor_new(); v = qapi_dealloc_get_visitor(md); - visit_type_%(name)s(v, &obj, NULL, NULL); + visit_type_%(c_name)s(v, &obj, NULL, NULL); qapi_dealloc_visitor_cleanup(md); } ''', - name=c_name(name)) + c_name=c_name(name)) return ret @@ -254,20 +229,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor): self._btin = None def _gen_type_cleanup(self, name): - self.decl += generate_type_cleanup_decl(name) - self.defn += generate_type_cleanup(name) + self.decl += gen_type_cleanup_decl(name) + self.defn += gen_type_cleanup(name) def visit_enum_type(self, name, info, values, prefix): - self._fwdecl += generate_enum(name, values, prefix) - self._fwdefn += generate_enum_lookup(name, values, prefix) + self._fwdecl += gen_enum(name, values, prefix) + self._fwdefn += gen_enum_lookup(name, values, prefix) def visit_array_type(self, name, info, element_type): if isinstance(element_type, QAPISchemaBuiltinType): self._btin += gen_fwd_object_or_array(name) self._btin += gen_array(name, element_type) - self._btin += generate_type_cleanup_decl(name) + self._btin += gen_type_cleanup_decl(name) if do_builtins: - self.defn += generate_type_cleanup(name) + self.defn += gen_type_cleanup(name) else: self._fwdecl += gen_fwd_object_or_array(name) self.decl += gen_array(name, element_type) diff --git a/qemu/scripts/qapi-visit.py b/qemu/scripts/qapi-visit.py index 6a61db29..74e96b93 100644 --- a/qemu/scripts/qapi-visit.py +++ b/qemu/scripts/qapi-visit.py @@ -18,18 +18,19 @@ import re implicit_structs_seen = set() struct_fields_seen = set() -def generate_visit_implicit_struct(type): - if type in implicit_structs_seen: +def gen_visit_implicit_struct(typ): + if typ in implicit_structs_seen: return '' - implicit_structs_seen.add(type) + implicit_structs_seen.add(typ) + ret = '' - if type.name not in struct_fields_seen: + if typ.name not in struct_fields_seen: # Need a forward declaration ret += mcgen(''' static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp); ''', - c_type=type.c_name()) + c_type=typ.c_name()) ret += mcgen(''' @@ -45,35 +46,35 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error * error_propagate(errp, err); } ''', - c_type=type.c_name()) + c_type=typ.c_name()) return ret -def generate_visit_struct_fields(name, members, base = None): +def gen_visit_struct_fields(name, base, members): struct_fields_seen.add(name) ret = '' if base: - ret += generate_visit_implicit_struct(base) + ret += gen_visit_implicit_struct(base) ret += mcgen(''' -static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp) +static void visit_type_%(c_name)s_fields(Visitor *m, %(c_name)s **obj, Error **errp) { Error *err = NULL; ''', - name=c_name(name)) + c_name=c_name(name)) push_indent() if base: ret += mcgen(''' -visit_type_implicit_%(type)s(m, &(*obj)->%(c_name)s, &err); +visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err); if (err) { goto out; } ''', - type=base.c_name(), c_name=c_name('base')) + c_type=base.c_name(), c_name=c_name('base')) for memb in members: if memb.optional: @@ -85,9 +86,9 @@ if (!err && (*obj)->has_%(c_name)s) { push_indent() ret += mcgen(''' -visit_type_%(type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err); +visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err); ''', - type=memb.type.c_name(), c_name=c_name(memb.name), + c_type=memb.type.c_name(), c_name=c_name(memb.name), name=memb.name) if memb.optional: @@ -102,7 +103,7 @@ if (err) { ''') pop_indent() - if re.search('^ *goto out\\;', ret, re.MULTILINE): + if re.search('^ *goto out;', ret, re.MULTILINE): ret += mcgen(''' out: @@ -114,7 +115,7 @@ out: return ret -def generate_visit_struct_body(name): +def gen_visit_struct_body(name): ret = mcgen(''' Error *err = NULL; @@ -129,30 +130,29 @@ def generate_visit_struct_body(name): error_propagate(errp, err); ''', name=name, c_name=c_name(name)) - return ret def gen_visit_struct(name, base, members): - ret = generate_visit_struct_fields(name, members, base) - + ret = gen_visit_struct_fields(name, base, members) ret += mcgen(''' -void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) +void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp) { ''', - name=c_name(name)) + c_name=c_name(name)) - ret += generate_visit_struct_body(name) + ret += gen_visit_struct_body(name) ret += mcgen(''' } ''') return ret + def gen_visit_list(name, element_type): return mcgen(''' -void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) +void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp) { Error *err = NULL; GenericList *i, **prev; @@ -165,7 +165,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e for (prev = (GenericList **)obj; !err && (i = visit_next_list(m, prev)) != NULL; prev = &i) { - %(name)s *native_i = (%(name)s *)i; + %(c_name)s *native_i = (%(c_name)s *)i; visit_type_%(c_elt_type)s(m, &native_i->value, NULL, &err); } @@ -176,10 +176,10 @@ out: error_propagate(errp, err); } ''', - name=c_name(name), - c_elt_type=element_type.c_name()) + c_name=c_name(name), c_elt_type=element_type.c_name()) -def generate_visit_enum(name): + +def gen_visit_enum(name): return mcgen(''' void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error **errp) @@ -189,36 +189,36 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error ''', c_name=c_name(name), name=name) + def gen_visit_alternate(name, variants): ret = mcgen(''' -void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) +void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp) { Error *err = NULL; - visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err); + visit_start_implicit_struct(m, (void**) obj, sizeof(%(c_name)s), &err); if (err) { goto out; } - visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err); + visit_get_next_type(m, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err); if (err) { goto out_end; } switch ((*obj)->kind) { ''', - name=c_name(name)) + c_name=c_name(name)) for var in variants.variants: - enum_full_value = c_enum_const(variants.tag_member.type.name, - var.name) ret += mcgen(''' - case %(enum_full_value)s: + case %(case)s: visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); break; ''', - enum_full_value = enum_full_value, - c_type=var.type.c_name(), - c_name=c_name(var.name)) + case=c_enum_const(variants.tag_member.type.name, + var.name), + c_type=var.type.c_name(), + c_name=c_name(var.name)) ret += mcgen(''' default: @@ -235,17 +235,18 @@ out: return ret + def gen_visit_union(name, base, variants): ret = '' if base: members = [m for m in base.members if m != variants.tag_member] - ret += generate_visit_struct_fields(name, members) + ret += gen_visit_struct_fields(name, None, members) for var in variants.variants: # Ugly special case for simple union TODO get rid of it if not var.simple_union_type(): - ret += generate_visit_implicit_struct(var.type) + ret += gen_visit_implicit_struct(var.type) ret += mcgen(''' @@ -263,19 +264,19 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error if base: ret += mcgen(''' - visit_type_%(name)s_fields(m, obj, &err); + visit_type_%(c_name)s_fields(m, obj, &err); if (err) { goto out_obj; } ''', - name=c_name(name)) + c_name=c_name(name)) - disc_key = variants.tag_member.name + tag_key = variants.tag_member.name if not variants.tag_name: # we pointlessly use a different key for simple unions - disc_key = 'type' + tag_key = 'type' ret += mcgen(''' - visit_type_%(disc_type)s(m, &(*obj)->%(c_name)s, "%(disc_key)s", &err); + visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err); if (err) { goto out_obj; } @@ -284,30 +285,37 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error } switch ((*obj)->%(c_name)s) { ''', - disc_type=variants.tag_member.type.c_name(), + c_type=variants.tag_member.type.c_name(), # TODO ugly special case for simple union # Use same tag name in C as on the wire to get rid of # it, then: c_name=c_name(variants.tag_member.name) c_name=c_name(variants.tag_name or 'kind'), - disc_key = disc_key) + name=tag_key) for var in variants.variants: # TODO ugly special case for simple union simple_union_type = var.simple_union_type() - if simple_union_type: - fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);' - else: - fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);' - - enum_full_value = c_enum_const(variants.tag_member.type.name, var.name) ret += mcgen(''' - case %(enum_full_value)s: - ''' + fmt + ''' - break; + case %(case)s: ''', - enum_full_value = enum_full_value, - c_type=(simple_union_type or var.type).c_name(), - c_name=c_name(var.name)) + case=c_enum_const(variants.tag_member.type.name, + var.name)) + if simple_union_type: + ret += mcgen(''' + visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err); +''', + c_type=simple_union_type.c_name(), + c_name=c_name(var.name)) + else: + ret += mcgen(''' + visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err); +''', + c_type=var.type.c_name(), + c_name=c_name(var.name)) + + ret += mcgen(''' + break; +''') ret += mcgen(''' default: @@ -328,6 +336,7 @@ out: return ret + def gen_visit_decl(name, scalar=False): c_type = c_name(name) + ' *' if not scalar: @@ -361,7 +370,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor): def visit_enum_type(self, name, info, values, prefix): self.decl += gen_visit_decl(name, scalar=True) - self.defn += generate_visit_enum(name) + self.defn += gen_visit_enum(name) def visit_array_type(self, name, info, element_type): decl = gen_visit_decl(name) @@ -437,7 +446,7 @@ fdef.write(mcgen(''' #include "qemu-common.h" #include "%(prefix)sqapi-visit.h" ''', - prefix = prefix)) + prefix=prefix)) fdecl.write(mcgen(''' #include "qapi/visitor.h" diff --git a/qemu/scripts/qapi.py b/qemu/scripts/qapi.py index e93234af..8365792d 100644 --- a/qemu/scripts/qapi.py +++ b/qemu/scripts/qapi.py @@ -1083,9 +1083,6 @@ class QAPISchema(object): self._def_exprs() self.check() - def get_exprs(self): - return [expr_elem['expr'] for expr_elem in self.exprs] - def _def_entity(self, ent): assert ent.name not in self._entity_dict self._entity_dict[ent.name] = ent @@ -1277,23 +1274,6 @@ class QAPISchema(object): # Code generation helpers # -def parse_args(typeinfo): - if isinstance(typeinfo, str): - struct = find_struct(typeinfo) - assert struct != None - typeinfo = struct['data'] - - for member in typeinfo: - argname = member - argentry = typeinfo[member] - optional = False - if member.startswith('*'): - argname = member[1:] - optional = True - # Todo: allow argentry to be OrderedDict, for providing the - # value of an optional argument. - yield (argname, argentry, optional) - def camel_case(name): new_name = '' first = True @@ -1376,67 +1356,9 @@ def c_name(name, protect=True): return "q_" + name return name.translate(c_name_trans) -# Map type @name to the C typedef name for the list form. -# -# ['Name'] -> 'NameList', ['x-Foo'] -> 'x_FooList', ['int'] -> 'intList' -def c_list_type(name): - return name + 'List' - -# Map type @value to the C typedef form. -# -# Used for converting 'type' from a 'member':'type' qapi definition -# into the alphanumeric portion of the type for a generated C parameter, -# as well as generated C function names. See c_type() for the rest of -# the conversion such as adding '*' on pointer types. -# 'int' -> 'int', '[x-Foo]' -> 'x_FooList', '__a.b_c' -> '__a_b_c' -def type_name(value): - if type(value) == list: - return c_list_type(value[0]) - if value in builtin_types.keys(): - return value - return c_name(value) - eatspace = '\033EATSPACE.' pointer_suffix = ' *' + eatspace -# Map type @name to its C type expression. -# If @is_param, const-qualify the string type. -# -# This function is used for computing the full C type of 'member':'name'. -# A special suffix is added in c_type() for pointer types, and it's -# stripped in mcgen(). So please notice this when you check the return -# value of c_type() outside mcgen(). -def c_type(value, is_param=False): - if value == 'str': - if is_param: - return 'const char' + pointer_suffix - return 'char' + pointer_suffix - - elif value == 'int': - return 'int64_t' - elif (value == 'int8' or value == 'int16' or value == 'int32' or - value == 'int64' or value == 'uint8' or value == 'uint16' or - value == 'uint32' or value == 'uint64'): - return value + '_t' - elif value == 'size': - return 'uint64_t' - elif value == 'bool': - return 'bool' - elif value == 'number': - return 'double' - elif type(value) == list: - return c_list_type(value[0]) + pointer_suffix - elif is_enum(value): - return c_name(value) - elif value == None: - return 'void' - elif value in events: - return camel_case(value) + 'Event' + pointer_suffix - else: - # complex type name - assert isinstance(value, str) and value != "" - return c_name(value) + pointer_suffix - def genindent(count): ret = "" for i in range(count): @@ -1490,18 +1412,18 @@ def guardend(name): ''', name=guardname(name)) -def generate_enum_lookup(name, values, prefix=None): +def gen_enum_lookup(name, values, prefix=None): ret = mcgen(''' -const char *const %(name)s_lookup[] = { +const char *const %(c_name)s_lookup[] = { ''', - name=c_name(name)) + c_name=c_name(name)) for value in values: index = c_enum_const(name, value, prefix) ret += mcgen(''' "%(value)s", ''', - index = index, value = value) + value=value) # Unicorn: We don't use C99 [ARRAY_INDICING] = Thing because # MSVC is still in the stone-age with this part of C compiler @@ -1510,43 +1432,38 @@ const char *const %(name)s_lookup[] = { ret += mcgen(''' NULL, }; -''', - max_index=max_index) +''') + return ret -def generate_enum(name, values, prefix=None): - name = c_name(name) - lookup_decl = mcgen(''' - -extern const char *const %(name)s_lookup[]; -''', - name=name) - - enum_decl = mcgen(''' - -typedef enum %(name)s { -''', - name=name) - +def gen_enum(name, values, prefix=None): # append automatically generated _MAX value - enum_values = values + [ 'MAX' ] + enum_values = values + ['MAX'] + ret = mcgen(''' + +typedef enum %(c_name)s { +''', + c_name=c_name(name)) i = 0 for value in enum_values: - enum_full_value = c_enum_const(name, value, prefix) - enum_decl += mcgen(''' - %(enum_full_value)s = %(i)d, + ret += mcgen(''' + %(c_enum)s = %(i)d, ''', - enum_full_value = enum_full_value, + c_enum=c_enum_const(name, value, prefix), i=i) i += 1 - enum_decl += mcgen(''' -} %(name)s; + ret += mcgen(''' +} %(c_name)s; ''', - name=name) + c_name=c_name(name)) - return enum_decl + lookup_decl + ret += mcgen(''' +extern const char *const %(c_name)s_lookup[]; +''', + c_name=c_name(name)) + return ret # # Common command line parsing