mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-05 19:29:39 +00:00
qapi: Clean up after recent conversions to QAPISchemaVisitor
Generate just 'FOO' instead of 'struct FOO' when possible. Drop helper functions that are now unused. Make pep8 and pylint reasonably happy. Rename generate_FOO() functions to gen_FOO() for consistency. Use more consistent and sensible variable names. Consistently use c_ for mapping keys when their value is a C identifier or type. Simplify gen_enum() and gen_visit_union() Consistently use single quotes for C text string literals. Backports commit e98859a9b96d71dea8f9af43325edd43c7effe66 from qemu
This commit is contained in:
parent
64e9fceab9
commit
d6866a50f6
|
@ -154,6 +154,7 @@ void qapi_free_uint8List(uint8List *obj);
|
||||||
|
|
||||||
#endif /* QAPI_TYPES_BUILTIN */
|
#endif /* QAPI_TYPES_BUILTIN */
|
||||||
|
|
||||||
|
|
||||||
typedef enum ErrorClass {
|
typedef enum ErrorClass {
|
||||||
ERROR_CLASS_GENERIC_ERROR = 0,
|
ERROR_CLASS_GENERIC_ERROR = 0,
|
||||||
ERROR_CLASS_COMMAND_NOT_FOUND = 1,
|
ERROR_CLASS_COMMAND_NOT_FOUND = 1,
|
||||||
|
@ -170,6 +171,7 @@ typedef struct ErrorClassList ErrorClassList;
|
||||||
typedef struct X86CPUFeatureWordInfo X86CPUFeatureWordInfo;
|
typedef struct X86CPUFeatureWordInfo X86CPUFeatureWordInfo;
|
||||||
|
|
||||||
typedef struct X86CPUFeatureWordInfoList X86CPUFeatureWordInfoList;
|
typedef struct X86CPUFeatureWordInfoList X86CPUFeatureWordInfoList;
|
||||||
|
|
||||||
typedef enum X86CPURegister32 {
|
typedef enum X86CPURegister32 {
|
||||||
X86_CPU_REGISTER32_EAX = 0,
|
X86_CPU_REGISTER32_EAX = 0,
|
||||||
X86_CPU_REGISTER32_EBX = 1,
|
X86_CPU_REGISTER32_EBX = 1,
|
||||||
|
|
|
@ -13,24 +13,26 @@
|
||||||
|
|
||||||
from qapi import *
|
from qapi import *
|
||||||
|
|
||||||
|
|
||||||
def gen_fwd_object_or_array(name):
|
def gen_fwd_object_or_array(name):
|
||||||
return mcgen('''
|
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):
|
def gen_array(name, element_type):
|
||||||
return mcgen('''
|
return mcgen('''
|
||||||
struct %(name)s {
|
struct %(c_name)s {
|
||||||
union {
|
union {
|
||||||
%(c_type)s value;
|
%(c_type)s value;
|
||||||
uint64_t padding;
|
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):
|
def gen_struct_field(name, typ, optional):
|
||||||
ret = ''
|
ret = ''
|
||||||
|
@ -46,7 +48,8 @@ def gen_struct_field(name, typ, optional):
|
||||||
c_type=typ.c_type(), c_name=c_name(name))
|
c_type=typ.c_type(), c_name=c_name(name))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_struct_fields(members):
|
|
||||||
|
def gen_struct_fields(members):
|
||||||
ret = ''
|
ret = ''
|
||||||
|
|
||||||
for memb in members:
|
for memb in members:
|
||||||
|
@ -55,18 +58,19 @@ def generate_struct_fields(members):
|
||||||
|
|
||||||
def gen_struct(name, base, members):
|
def gen_struct(name, base, members):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
struct %(name)s {
|
struct %(c_name)s {
|
||||||
''',
|
''',
|
||||||
name=c_name(name))
|
c_name=c_name(name))
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += gen_struct_field('base', base, False)
|
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
|
# Make sure that all structs have at least one field; this avoids
|
||||||
# potential issues with attempting to malloc space for zero-length structs
|
# potential issues with attempting to malloc space for zero-length
|
||||||
# in C, and also incompatibility with C++ (where an empty struct is size 1).
|
# structs in C, and also incompatibility with C++ (where an empty
|
||||||
|
# struct is size 1).
|
||||||
if not base and not members:
|
if not base and not members:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
char qapi_dummy_field_for_empty_struct;
|
char qapi_dummy_field_for_empty_struct;
|
||||||
|
@ -78,37 +82,6 @@ struct %(name)s {
|
||||||
|
|
||||||
return ret
|
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):
|
def gen_alternate_qtypes_decl(name):
|
||||||
return mcgen('''
|
return mcgen('''
|
||||||
|
@ -117,12 +90,13 @@ extern const int %(c_name)s_qtypes[];
|
||||||
''',
|
''',
|
||||||
c_name=c_name(name))
|
c_name=c_name(name))
|
||||||
|
|
||||||
|
|
||||||
def gen_alternate_qtypes(name, variants):
|
def gen_alternate_qtypes(name, variants):
|
||||||
ret = mcgen('''
|
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:
|
for var in variants.variants:
|
||||||
qtype = var.type.alternate_qtype()
|
qtype = var.type.alternate_qtype()
|
||||||
|
@ -131,6 +105,7 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
[%(qtype)s] = %(enum_const)s,
|
[%(qtype)s] = %(enum_const)s,
|
||||||
''',
|
''',
|
||||||
|
qtype=qtype,
|
||||||
enum_const=c_enum_const(variants.tag_member.type.name,
|
enum_const=c_enum_const(variants.tag_member.type.name,
|
||||||
var.name))
|
var.name))
|
||||||
|
|
||||||
|
@ -142,26 +117,24 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
|
||||||
|
|
||||||
|
|
||||||
def gen_union(name, base, variants):
|
def gen_union(name, base, variants):
|
||||||
name = c_name(name)
|
|
||||||
|
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
struct %(name)s {
|
struct %(c_name)s {
|
||||||
''',
|
''',
|
||||||
name=name)
|
c_name=c_name(name))
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
/* Members inherited from %(c_name)s: */
|
/* Members inherited from %(c_name)s: */
|
||||||
''',
|
''',
|
||||||
c_name=c_name(base.name))
|
c_name=c_name(base.name))
|
||||||
ret += generate_struct_fields(base.members)
|
ret += gen_struct_fields(base.members)
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
/* Own members: */
|
/* Own members: */
|
||||||
''')
|
''')
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
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
|
# 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
|
# has a branch named 'data'? We use it in qapi-visit.py to decide
|
||||||
|
@ -196,17 +169,19 @@ struct %(name)s {
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_type_cleanup_decl(name):
|
|
||||||
|
def gen_type_cleanup_decl(name):
|
||||||
ret = mcgen('''
|
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
|
return ret
|
||||||
|
|
||||||
def generate_type_cleanup(name):
|
|
||||||
|
def gen_type_cleanup(name):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
|
|
||||||
void qapi_free_%(name)s(%(name)s *obj)
|
void qapi_free_%(c_name)s(%(c_name)s *obj)
|
||||||
{
|
{
|
||||||
QapiDeallocVisitor *md;
|
QapiDeallocVisitor *md;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
@ -217,11 +192,11 @@ void qapi_free_%(name)s(%(name)s *obj)
|
||||||
|
|
||||||
md = qapi_dealloc_visitor_new();
|
md = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(md);
|
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);
|
qapi_dealloc_visitor_cleanup(md);
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
name=c_name(name))
|
c_name=c_name(name))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,20 +229,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
|
||||||
self._btin = None
|
self._btin = None
|
||||||
|
|
||||||
def _gen_type_cleanup(self, name):
|
def _gen_type_cleanup(self, name):
|
||||||
self.decl += generate_type_cleanup_decl(name)
|
self.decl += gen_type_cleanup_decl(name)
|
||||||
self.defn += generate_type_cleanup(name)
|
self.defn += gen_type_cleanup(name)
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, values, prefix):
|
||||||
self._fwdecl += generate_enum(name, values, prefix)
|
self._fwdecl += gen_enum(name, values, prefix)
|
||||||
self._fwdefn += generate_enum_lookup(name, values, prefix)
|
self._fwdefn += gen_enum_lookup(name, values, prefix)
|
||||||
|
|
||||||
def visit_array_type(self, name, info, element_type):
|
def visit_array_type(self, name, info, element_type):
|
||||||
if isinstance(element_type, QAPISchemaBuiltinType):
|
if isinstance(element_type, QAPISchemaBuiltinType):
|
||||||
self._btin += gen_fwd_object_or_array(name)
|
self._btin += gen_fwd_object_or_array(name)
|
||||||
self._btin += gen_array(name, element_type)
|
self._btin += gen_array(name, element_type)
|
||||||
self._btin += generate_type_cleanup_decl(name)
|
self._btin += gen_type_cleanup_decl(name)
|
||||||
if do_builtins:
|
if do_builtins:
|
||||||
self.defn += generate_type_cleanup(name)
|
self.defn += gen_type_cleanup(name)
|
||||||
else:
|
else:
|
||||||
self._fwdecl += gen_fwd_object_or_array(name)
|
self._fwdecl += gen_fwd_object_or_array(name)
|
||||||
self.decl += gen_array(name, element_type)
|
self.decl += gen_array(name, element_type)
|
||||||
|
|
|
@ -18,18 +18,19 @@ import re
|
||||||
implicit_structs_seen = set()
|
implicit_structs_seen = set()
|
||||||
struct_fields_seen = set()
|
struct_fields_seen = set()
|
||||||
|
|
||||||
def generate_visit_implicit_struct(type):
|
def gen_visit_implicit_struct(typ):
|
||||||
if type in implicit_structs_seen:
|
if typ in implicit_structs_seen:
|
||||||
return ''
|
return ''
|
||||||
implicit_structs_seen.add(type)
|
implicit_structs_seen.add(typ)
|
||||||
|
|
||||||
ret = ''
|
ret = ''
|
||||||
if type.name not in struct_fields_seen:
|
if typ.name not in struct_fields_seen:
|
||||||
# Need a forward declaration
|
# Need a forward declaration
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp);
|
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('''
|
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);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
c_type=type.c_name())
|
c_type=typ.c_name())
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_visit_struct_fields(name, members, base = None):
|
def gen_visit_struct_fields(name, base, members):
|
||||||
struct_fields_seen.add(name)
|
struct_fields_seen.add(name)
|
||||||
|
|
||||||
ret = ''
|
ret = ''
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += generate_visit_implicit_struct(base)
|
ret += gen_visit_implicit_struct(base)
|
||||||
|
|
||||||
ret += mcgen('''
|
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;
|
Error *err = NULL;
|
||||||
|
|
||||||
''',
|
''',
|
||||||
name=c_name(name))
|
c_name=c_name(name))
|
||||||
push_indent()
|
push_indent()
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
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) {
|
if (err) {
|
||||||
goto out;
|
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:
|
for memb in members:
|
||||||
if memb.optional:
|
if memb.optional:
|
||||||
|
@ -85,9 +86,9 @@ if (!err && (*obj)->has_%(c_name)s) {
|
||||||
push_indent()
|
push_indent()
|
||||||
|
|
||||||
ret += mcgen('''
|
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)
|
name=memb.name)
|
||||||
|
|
||||||
if memb.optional:
|
if memb.optional:
|
||||||
|
@ -102,7 +103,7 @@ if (err) {
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pop_indent()
|
pop_indent()
|
||||||
if re.search('^ *goto out\\;', ret, re.MULTILINE):
|
if re.search('^ *goto out;', ret, re.MULTILINE):
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -114,7 +115,7 @@ out:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def generate_visit_struct_body(name):
|
def gen_visit_struct_body(name):
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
|
@ -129,30 +130,29 @@ def generate_visit_struct_body(name):
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
''',
|
''',
|
||||||
name=name, c_name=c_name(name))
|
name=name, c_name=c_name(name))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def gen_visit_struct(name, base, members):
|
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('''
|
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('''
|
ret += mcgen('''
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_list(name, element_type):
|
def gen_visit_list(name, element_type):
|
||||||
return mcgen('''
|
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;
|
Error *err = NULL;
|
||||||
GenericList *i, **prev;
|
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;
|
for (prev = (GenericList **)obj;
|
||||||
!err && (i = visit_next_list(m, prev)) != NULL;
|
!err && (i = visit_next_list(m, prev)) != NULL;
|
||||||
prev = &i) {
|
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);
|
visit_type_%(c_elt_type)s(m, &native_i->value, NULL, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,10 +176,10 @@ out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
''',
|
''',
|
||||||
name=c_name(name),
|
c_name=c_name(name), c_elt_type=element_type.c_name())
|
||||||
c_elt_type=element_type.c_name())
|
|
||||||
|
|
||||||
def generate_visit_enum(name):
|
|
||||||
|
def gen_visit_enum(name):
|
||||||
return mcgen('''
|
return mcgen('''
|
||||||
|
|
||||||
void visit_type_%(c_name)s(Visitor *m, %(c_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)
|
||||||
|
@ -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)
|
c_name=c_name(name), name=name)
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_alternate(name, variants):
|
def gen_visit_alternate(name, variants):
|
||||||
ret = mcgen('''
|
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;
|
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) {
|
if (err) {
|
||||||
goto out;
|
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) {
|
if (err) {
|
||||||
goto out_end;
|
goto out_end;
|
||||||
}
|
}
|
||||||
switch ((*obj)->kind) {
|
switch ((*obj)->kind) {
|
||||||
''',
|
''',
|
||||||
name=c_name(name))
|
c_name=c_name(name))
|
||||||
|
|
||||||
for var in variants.variants:
|
for var in variants.variants:
|
||||||
enum_full_value = c_enum_const(variants.tag_member.type.name,
|
|
||||||
var.name)
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
case %(enum_full_value)s:
|
case %(case)s:
|
||||||
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
|
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
|
||||||
break;
|
break;
|
||||||
''',
|
''',
|
||||||
enum_full_value = enum_full_value,
|
case=c_enum_const(variants.tag_member.type.name,
|
||||||
c_type=var.type.c_name(),
|
var.name),
|
||||||
c_name=c_name(var.name))
|
c_type=var.type.c_name(),
|
||||||
|
c_name=c_name(var.name))
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
default:
|
default:
|
||||||
|
@ -235,17 +235,18 @@ out:
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_union(name, base, variants):
|
def gen_visit_union(name, base, variants):
|
||||||
ret = ''
|
ret = ''
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
members = [m for m in base.members if m != variants.tag_member]
|
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:
|
for var in variants.variants:
|
||||||
# Ugly special case for simple union TODO get rid of it
|
# Ugly special case for simple union TODO get rid of it
|
||||||
if not var.simple_union_type():
|
if not var.simple_union_type():
|
||||||
ret += generate_visit_implicit_struct(var.type)
|
ret += gen_visit_implicit_struct(var.type)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
|
@ -263,19 +264,19 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(name)s_fields(m, obj, &err);
|
visit_type_%(c_name)s_fields(m, obj, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out_obj;
|
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:
|
if not variants.tag_name:
|
||||||
# we pointlessly use a different key for simple unions
|
# we pointlessly use a different key for simple unions
|
||||||
disc_key = 'type'
|
tag_key = 'type'
|
||||||
ret += mcgen('''
|
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) {
|
if (err) {
|
||||||
goto out_obj;
|
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) {
|
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
|
# TODO ugly special case for simple union
|
||||||
# Use same tag name in C as on the wire to get rid of
|
# Use same tag name in C as on the wire to get rid of
|
||||||
# it, then: c_name=c_name(variants.tag_member.name)
|
# it, then: c_name=c_name(variants.tag_member.name)
|
||||||
c_name=c_name(variants.tag_name or 'kind'),
|
c_name=c_name(variants.tag_name or 'kind'),
|
||||||
disc_key = disc_key)
|
name=tag_key)
|
||||||
|
|
||||||
for var in variants.variants:
|
for var in variants.variants:
|
||||||
# TODO ugly special case for simple union
|
# TODO ugly special case for simple union
|
||||||
simple_union_type = var.simple_union_type()
|
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('''
|
ret += mcgen('''
|
||||||
case %(enum_full_value)s:
|
case %(case)s:
|
||||||
''' + fmt + '''
|
|
||||||
break;
|
|
||||||
''',
|
''',
|
||||||
enum_full_value = enum_full_value,
|
case=c_enum_const(variants.tag_member.type.name,
|
||||||
c_type=(simple_union_type or var.type).c_name(),
|
var.name))
|
||||||
c_name=c_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('''
|
ret += mcgen('''
|
||||||
default:
|
default:
|
||||||
|
@ -328,6 +336,7 @@ out:
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_decl(name, scalar=False):
|
def gen_visit_decl(name, scalar=False):
|
||||||
c_type = c_name(name) + ' *'
|
c_type = c_name(name) + ' *'
|
||||||
if not scalar:
|
if not scalar:
|
||||||
|
@ -361,7 +370,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, values, prefix):
|
def visit_enum_type(self, name, info, values, prefix):
|
||||||
self.decl += gen_visit_decl(name, scalar=True)
|
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):
|
def visit_array_type(self, name, info, element_type):
|
||||||
decl = gen_visit_decl(name)
|
decl = gen_visit_decl(name)
|
||||||
|
@ -437,7 +446,7 @@ fdef.write(mcgen('''
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "%(prefix)sqapi-visit.h"
|
#include "%(prefix)sqapi-visit.h"
|
||||||
''',
|
''',
|
||||||
prefix = prefix))
|
prefix=prefix))
|
||||||
|
|
||||||
fdecl.write(mcgen('''
|
fdecl.write(mcgen('''
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
|
|
|
@ -1083,9 +1083,6 @@ class QAPISchema(object):
|
||||||
self._def_exprs()
|
self._def_exprs()
|
||||||
self.check()
|
self.check()
|
||||||
|
|
||||||
def get_exprs(self):
|
|
||||||
return [expr_elem['expr'] for expr_elem in self.exprs]
|
|
||||||
|
|
||||||
def _def_entity(self, ent):
|
def _def_entity(self, ent):
|
||||||
assert ent.name not in self._entity_dict
|
assert ent.name not in self._entity_dict
|
||||||
self._entity_dict[ent.name] = ent
|
self._entity_dict[ent.name] = ent
|
||||||
|
@ -1277,23 +1274,6 @@ class QAPISchema(object):
|
||||||
# Code generation helpers
|
# 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):
|
def camel_case(name):
|
||||||
new_name = ''
|
new_name = ''
|
||||||
first = True
|
first = True
|
||||||
|
@ -1376,67 +1356,9 @@ def c_name(name, protect=True):
|
||||||
return "q_" + name
|
return "q_" + name
|
||||||
return name.translate(c_name_trans)
|
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.'
|
eatspace = '\033EATSPACE.'
|
||||||
pointer_suffix = ' *' + eatspace
|
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):
|
def genindent(count):
|
||||||
ret = ""
|
ret = ""
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
|
@ -1490,18 +1412,18 @@ def guardend(name):
|
||||||
''',
|
''',
|
||||||
name=guardname(name))
|
name=guardname(name))
|
||||||
|
|
||||||
def generate_enum_lookup(name, values, prefix=None):
|
def gen_enum_lookup(name, values, prefix=None):
|
||||||
ret = mcgen('''
|
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:
|
for value in values:
|
||||||
index = c_enum_const(name, value, prefix)
|
index = c_enum_const(name, value, prefix)
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
"%(value)s",
|
"%(value)s",
|
||||||
''',
|
''',
|
||||||
index = index, value = value)
|
value=value)
|
||||||
|
|
||||||
# Unicorn: We don't use C99 [ARRAY_INDICING] = Thing because
|
# Unicorn: We don't use C99 [ARRAY_INDICING] = Thing because
|
||||||
# MSVC is still in the stone-age with this part of C compiler
|
# 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('''
|
ret += mcgen('''
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
''',
|
''')
|
||||||
max_index=max_index)
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def generate_enum(name, values, prefix=None):
|
def gen_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
|
# 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
|
i = 0
|
||||||
for value in enum_values:
|
for value in enum_values:
|
||||||
enum_full_value = c_enum_const(name, value, prefix)
|
ret += mcgen('''
|
||||||
enum_decl += mcgen('''
|
%(c_enum)s = %(i)d,
|
||||||
%(enum_full_value)s = %(i)d,
|
|
||||||
''',
|
''',
|
||||||
enum_full_value = enum_full_value,
|
c_enum=c_enum_const(name, value, prefix),
|
||||||
i=i)
|
i=i)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
enum_decl += mcgen('''
|
ret += mcgen('''
|
||||||
} %(name)s;
|
} %(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
|
# Common command line parsing
|
||||||
|
|
Loading…
Reference in a new issue